home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / tcp_ip / tnos / tnos100s / convers.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-24  |  80.6 KB  |  3,217 lines

  1. /* convers server - based on conversd written by DK5SG
  2.  * ported to WNOS by DB3FL - 9109xx/9110xx
  3.  * ported to NOS by PE1NMB - 920120
  4.  * Mods by PA0GRI
  5.  * Cleanup, and additional mods by WG7J
  6.  * Major additions, rewrites, enhancements by KO4KS
  7.  */
  8.  
  9. #define extern extern far
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <time.h>
  13. #include <ctype.h>
  14. #ifdef    UNIX
  15. #include <sys/types.h>
  16. #include <sys/stat.h>
  17. #endif
  18. #include <io.h>
  19. #include "global.h"
  20. #include "config.h"
  21. #ifdef MAILBOX
  22. #include "mailbox.h"
  23. #include "netuser.h"
  24. #endif
  25. #include "pktdrvr.h"
  26. #include "timer.h"
  27. #include "cmdparse.h"
  28. #include "socket.h"
  29. #include "session.h"
  30. #include "files.h"
  31. #include "ax25.h"
  32. #ifdef LZW
  33. #include "lzw.h"
  34. #endif
  35.  
  36. char stars[] = "*** ";
  37.  
  38. #ifdef CONVERS
  39.  
  40. #pragma option -zEMYFAR
  41.  
  42. #define    LINK    1
  43. #define space
  44.  
  45.  
  46. #ifdef LZW
  47. void togglelzw __ARGS((int soc, int mode));
  48. #endif
  49.  
  50. #ifdef LINK
  51. struct proc *Linker;
  52. static void connect_permlinks __ARGS((int a,void *b,void *c));
  53. static void update_permlinks __ARGS((char *name,struct convection *cp));
  54. #endif
  55. static void cmdsummary_command __ARGS((struct convection *cp));
  56. static void personal_command __ARGS((struct convection *cp));
  57. static void nickname_command __ARGS((struct convection *cp));
  58. static void convcolorchange __ARGS((struct convection *p, unsigned char *str));
  59. static void roll_command __ARGS((struct convection *cp));
  60. static void cut_command __ARGS((struct convection *cp));
  61. void save_personal __ARGS((struct convection *cp));
  62. void conv_incom __ARGS((int s,void *t,void *p));
  63. extern void statlog __ARGS((char *buf));
  64.  
  65. int Sconv = -1;
  66. static int ConvNet0 = 0;
  67. static int TimeStamp = 0;
  68. extern char Chostname[];
  69. extern int Conflogins;
  70. #ifdef space
  71. static char cnumber[] = "*** Channel numbers must be in the range 0..%d.\n";
  72. #else
  73. static char cnumber[] = "* range 0..%d.\n";
  74. #endif
  75.  
  76. static char DFAR trailer[] = "***\n";
  77. static char DFAR string15[] = "%*s %15s";
  78. static char msgtext[] = "<*%s*>: %s\n";
  79. static char DFAR theysigned[] = "%s%s signed o%s at %s.\n";
  80. static char DFAR theyswitched[] = "%s%s switched to channel %d at %s.\n";
  81. static char DFAR conversd[] = "conversd";
  82. static char DFAR shortlist[] = "%-8.8s %-12s %s\n";
  83. static char DFAR fullstr[] = "%s";
  84. static char DFAR fullstrcr[] = "%s\n";
  85. static char sosorry[] = "*** Sorry, ";
  86. static char DFAR sorry[] = "%s%s Net on %s %d!\n";
  87. static char DFAR busystr[] = "%s'%s' is already a %s!\n";
  88. static char DFAR logfilestr[] = "%sLogfile is %sed\n";
  89. static char DFAR netcontrolstr[] = "Net Control";
  90. static char DFAR privatestr[] = "Closed";
  91. static char DFAR clearedstr[] = "cleared";
  92. static char DFAR passwordstr[] = "Password";
  93. static char DFAR nowchannel[] = "%sNow on %s %d (%d user%s).\n";
  94. static char DFAR nicknamestr[] = "%s%s%sset to '%s'.\n";
  95. static char DFAR channelstr[] = "Channel";
  96. static char DFAR systemstr[] = "SYSTEM";
  97. static char unknownstr[] = "*** Unknown ";
  98. static char DFAR unkcmdstr[] = "%scommand '/%s'.%s";
  99. static char DFAR nouserstr[] = "%suser!\n";
  100. static char DFAR gethelpstr[] = " Type /HELP for help.\n";
  101. static char DFAR noopenstr[] = "Can't open '%s'\n";
  102. static char DFAR activenetstr[] = "%sActive Net '%s'\n";
  103. static char DFAR net2str[] = "%sNet %s %s\n";
  104. static char DFAR conferencestr[] = "*** Conference @ ";
  105. static char DFAR namecmdstr[] = "%sPlease login with '/na <call>'\n";
  106. static char DFAR nonetstr[] = "%sNo Net!\n";
  107. static char DFAR recheckstr[] = "*** Recheck";
  108. static char DFAR questionstr[] = "*** Question";
  109. static char DFAR nicknmstr[] = "Nickname ";
  110. static char DFAR tmstr[] = "Time";
  111. static char DFAR userstr[] = "User";
  112. static char DFAR hoststr[] = "Host";
  113. static char DFAR newuserstr[] = "%sNew user '%s' has entered conference area on channel '%d'";
  114. static char DFAR urnotstr[] = "%sYou are not %s\n";
  115. static char DFAR urassigned[] = "%s'%s' has assigned you as %s on %s %d\n";
  116. static char DFAR wrongchannel[] = "%s%s '%s' not on this %s\n";
  117. static char DFAR openminutes[] = "%sMinutes starting at %s\n%sNet '%s' - %s is '%s'\n";
  118. static char DFAR closeminutes[] = "%sMinutes ending at %s\n";
  119. static char DFAR headerstr[] = "User       Host              Via             Channel   Time Personal\n";
  120. static char DFAR userdata[] = "%-10s %-16s %-16s %7d  %s %s\n";
  121. static char DFAR hinvi[] = "/\377\200INVI %s %s %d %s\n";
  122. static char DFAR huser[] = "/\377\200USER %s %s %d %d %d\n";
  123. static char DFAR udatstr[] = "/\377\200UDAT %s %s %s %d %s\n";
  124. static char DFAR bumpstr[] = "/\377\200BUMP %s %d\n";
  125. static char DFAR ndatstr[] = "/\377\200NDAT %d %d %d %d %d %s|%s|%s|\n";
  126. static char DFAR quesstr[] = "/\377\200QUES %d %c %s %s\n";
  127. static char DFAR umsgstr[] = "/\377\200UMSG %s %s %s\n";
  128. static char DFAR cmsgstr[] = "/\377\200CMSG %s %d |%s|\n";
  129. static char DFAR hhoststr[] = "/\377\200HOST %s\n";
  130. static char DFAR huserstr[] = "/\377\200USER %s %s %d %d %d\n";
  131. static char DFAR loopstr[] = "/\377\200LOOP %s %s %s\n";
  132. static char DFAR SYSCOLORS[] = "0C";
  133. static char DFAR TEXTCOLORS[] = "09";
  134. static char DFAR INFOCOLORS[] = "0B";
  135. static char DFAR INPUTCOLORS[] = "0F";
  136. static char DFAR summary[] = "%sConference Bridge command summary:\n ";
  137. static char DFAR modeis[] = "Mode is: %s\n";
  138. static char DFAR acceptstr[] = "Accept";
  139. static char DFAR refuse[] = "Refuse";
  140. static char DFAR redun[] = "Conf. redundancy timer (sec)";
  141. static char DFAR entrystr[] = "Conf. entry channel";
  142. static char DFAR allownets[] = "Allow Nets on Channel 0";
  143. static char DFAR timestampstr[] = "Timestamp all user messages";
  144. static char DFAR maxwaitstr[] = "Re-link max wait (sec)";
  145. static char DFAR hostqueuestr[] = "Max. Host Queue (bytes)";
  146. static char DFAR userqueuestr[] = "Max. User Queue (bytes)";
  147. static char DFAR motdstr[] = "Conference MOTD: %s\n";
  148. static char ff_str[] = "ff";
  149. static char n_str[] = "n";
  150. static char empty[] = "";
  151. static char DFAR timestampfmt[] = "<*%s:%s*>:";
  152. static char DFAR nontimestampfmt[] = "<*%s*>:";
  153. static char DFAR timestampfmt2[] = "<%s:%s>:";
  154. static char DFAR nontimestampfmt2[] = "<%s>:";
  155. static char DFAR alreadyon[] = "%s%s %s is already on this channel.";
  156. static char DFAR exitingstr[] = "Exiting %s%s\n";
  157. static char DFAR welcome[] = "%s%s%sNet '%s' - %s is '%s'... Welcome, %s!\n";
  158. static char DFAR welcomeback[] = "%sWelcome back, %s\n";
  159. static char DFAR noinvite[] = "%s%s net, only %s can invite\n";
  160. static char DFAR linkhdr[] = "Host             State         Since%s\n";
  161. static char DFAR linkhdr2[] = " NextTry Tries Queue Receivd Xmitted";
  162. static char DFAR nosuchuser[] = "%sNo such user: %s.\n";
  163. static char DFAR online[] = "%sThere are %d users online\n";
  164. static char DFAR groupsavail[] = "%sThere %s %d group%s available\n";
  165. static char DFAR colorstatus[] = "%sCurrently ANSI Color graphics are O%s\n";
  166. static char DFAR personalset[] = "%sPersonal data set to: %s\n";
  167. static char DFAR quotebanner[] = "*** Quote of the day:\n";
  168. static char DFAR whobanner[] = "%s             %s        %s Personal\n";
  169. static char DFAR rollstr[] = "%s'%s' has rolled a %d and a %d for a total of %d! %s";
  170. static char DFAR cutstr[] = "%s'%s' has cut the deck and selected the %s of %s! %s";
  171. static char DFAR gloghdr[] = "*** Current Check-ins\n";
  172. static char DFAR glogstr[] = "    %s     %s         In    %s\n";
  173. static char DFAR grouphdr[] = "%sAvailable Groups:\n Channel  Group Name\n =======  ==========\n";
  174.  
  175. #ifdef space
  176. static char DFAR youare[] = "%sYou are %son channel %d.\n";
  177. static char DFAR amessage[] = "\n*** Message from ";
  178. static char DFAR invitetext[] = "%s%s at %s ...\n%sPlease join conference channel %d.\n";
  179. static char DFAR mbinvitetext[] = "%s%s at %s ...\n%sPlease type 'CONF %d' to join conference channel %d.\n";
  180. static char DFAR responsetext[] = "%sInvitation sent to %s @ %s";
  181. #else
  182. static char DFAR youare[] = "%sOn channel %d.\n";
  183. static char DFAR amessage[] = "\n*** Msg frm ";
  184. static char DFAR invitetext[] = "%s%s at %s ...\n%sPse join ch. %d.\n";
  185. static char DFAR mbinvitetext[] = "%s at %s ...\n%sPse hit 'CONF %d' for conference ch. %d.\n";
  186. static char DFAR responsetext[] = "%ssent to %s @ %s";
  187. #endif
  188.  
  189. #define MAXCHANNEL     ((int) 32767)
  190. #define LINELEN     256
  191. #define MAX_WAITTIME    (60*60*3)
  192. #define NAMELEN 16
  193.  
  194. struct convection {
  195.     int  type;            /* Connection type */
  196. #define CT_UNKNOWN      0
  197. #define CT_USER         1
  198. #define CT_HOST         2
  199. #define CT_CLOSED       3
  200.     char  name[NAMELEN+1];         /* Name of user or host */
  201.     char  host[NAMELEN+1];         /* Name of host where user is logged on */
  202.     char  nickname[NAMELEN+1];        /* Nickname of user */
  203.     char  password[NAMELEN+1];        /* Password of user */   
  204.     struct convection *via;        /* Pointer to neighbor host */
  205.     char *data;                 /* room for some personal data */
  206.     int channel;            /* Channel number */
  207.     int net;            /* Channel of controlled net */
  208.     int32 nettime;            /* Time entered channel (used by nets) */
  209.     int32 time;            /* Connect time */
  210.     int maxq;           /* Maximum outstanding data before link reset */
  211.     int locked;            /* Set if mesg already sent */
  212.     int fd;                /* Socket descriptor */
  213.     int flags;            /* User flags */
  214. #define CLOSE_SOCK  1
  215. #define USE_SOUND   2
  216. #define CHANGED_INFO 4
  217. #define USE_LZW 8
  218. #define USE_COLOR 16
  219.     char colorset[2];        /* current color set */
  220.     /* This buffer is only needed for local users; a lot of space is wasted
  221.      * for users from other hosts (256 bytes per user!). Fixed 930728 - WG7J
  222.      * char ibuf[LINELEN];
  223.      */
  224.     char *ibuf;                      /* Input buffer */
  225.     int  received;            /* Number of bytes received */
  226.     int  xmitted;            /* Number of bytes transmitted */
  227.     int  paged;            /* Last channel invited to (paged) */
  228.     struct convection *next;    /* Linked list pointer */
  229. };
  230.  
  231. #define CM_UNKNOWN    (1 << CT_UNKNOWN)
  232. #define CM_USER        (1 << CT_USER)
  233. #define CM_HOST        (1 << CT_HOST)
  234. #define CM_CLOSED    (1 << CT_CLOSED)
  235.  
  236. #define NULLCONNECTION    ((struct convection *) 0)
  237.  
  238. static struct convection *convections;
  239.  
  240. struct permlink {
  241.     char name[NAMELEN+1];   /* Name of link */
  242.     int32 addr;             /* address to link to */
  243.     struct convection *convection;    /* Pointer to associated connection */
  244.     int32 statetime;        /* Time of last (dis)connect */
  245.     int  tries;            /* Number of connect tries */
  246.     int32 waittime;            /* Time between connect tries */
  247.     int32 retrytime;        /* Time of next connect try */
  248.     int fd;                /* socket descriptor */
  249.     struct permlink *next;        /* Linked list pointer */
  250. };
  251. #define NULLPERMLINK ((struct permlink *) 0)
  252.  
  253. static struct permlink *permlinks;
  254.  
  255. struct filter_link {
  256.     struct filter_link *next;
  257.     int32 addr;
  258. };
  259. #define NULLFL ((struct filter_link *) 0)
  260.  
  261. static struct filter_link *Filterlinks;
  262. static int FilterMode;
  263.  
  264. #define CNAMELEN 16
  265. char Chostname[CNAMELEN+1];
  266.  
  267. char *confMOTD = NULL;
  268.  
  269. struct group    {
  270.     int        channel;    /* channel # for this group info */
  271.     char         name[34];    /* group's name */
  272.     char        password[NAMELEN+1];    /* password required to enter group */
  273.     char        moderator[NAMELEN+1];    /* real name of current moderator */
  274.     FILE        *qfile;        /* stream of current question file */
  275.     short        nextq;        /* last question number in qfile */
  276.     short        totalq;        /* total questions in qfile */
  277.     FILE        *logfile;    /* stream of current logfile */
  278.     char            logged;         /* status of log file (1=open) */
  279.     char        private;    /* is it private (1 = yes) */
  280.     struct group     *next;        /* next group in queue */
  281. };
  282.  
  283. #define NULLGROUP ((struct group *) 0)
  284. #define NOCONTROL ((struct group *) -1)
  285.  
  286. static char nonetoverride;
  287. static struct group *groups;
  288. static struct group * find_group __ARGS((int channel));
  289. static void bye_command __ARGS((struct convection *cp));
  290. static void nonet_command __ARGS((struct convection *cp));
  291. static void process_question __ARGS((int channel, char type, char *name, char *cptr));
  292. static void glog_command __ARGS((struct convection *cp));
  293. extern int deleteserver __ARGS((int *mysocket));
  294. extern char *confMOTD;
  295. extern char Ccall[AXALEN];
  296.  
  297.  
  298. static int docfilter __ARGS((int argc,char *argv[],void *p));
  299. static int dochostname __ARGS((int argc,char *argv[],void *p));
  300. static int dociface __ARGS((int argc,char *argv[],void *p));
  301. static int doconfcall __ARGS((int argc,char *argv[],void *p));
  302. static int doclink __ARGS((int argc,char *argv[],void *p));
  303. static int doct4 __ARGS((int argc,char *argv[],void *p));
  304. static int doentrychannel __ARGS((int argc,char *argv[],void *p));
  305. static int doconfmotd __ARGS((int argc,char *argv[],void *p));
  306. static int doconvnet0 __ARGS((int argc,char *argv[],void *p));
  307. static int dotimestamp __ARGS((int argc,char *argv[],void *p));
  308. static int docmaxwait __ARGS((int argc,char *argv[],void *p));
  309. static int dohmaxq __ARGS((int argc,char *argv[],void *p));
  310. static int doumaxq __ARGS((int argc,char *argv[],void *p));
  311.  
  312. static struct cmds DFAR Ccmds[] = {
  313.     "entrychannel", doentrychannel, 0, 0, NULLCHAR,
  314.     "filter",    docfilter,   0, 0, NULLCHAR,
  315.     "hmaxq",    dohmaxq,    0, 0, NULLCHAR,
  316.     "hostname", dochostname,0, 0, NULLCHAR,
  317.     "interface",dociface,   0, 0, NULLCHAR,
  318. #ifdef LINK
  319.     "link",     doclink,    0, 0, NULLCHAR,
  320. #endif
  321.     "maxwait",  docmaxwait, 0, 0, NULLCHAR,
  322. #ifdef AX25
  323.     "motd",    doconfmotd, 0, 0, NULLCHAR,
  324.     "mycall",   doconfcall, 0, 0, NULLCHAR,
  325. #endif
  326.     "net0",    doconvnet0, 0, 0, NULLCHAR,
  327. #ifdef AX25
  328.     "t4",       doct4,      0, 0, NULLCHAR,
  329.     "timestamp",dotimestamp,0, 0, NULLCHAR,
  330. #endif
  331.     "umaxq",    doumaxq,    0, 0, NULLCHAR,
  332.     NULLCHAR,
  333. };
  334.  
  335. /* Multiplexer for top-level convers command */
  336. int
  337. doconvers(argc,argv,p)
  338. int argc;
  339. char *argv[];
  340. void *p;
  341. {
  342.     return subcmd(Ccmds,argc,argv,p);
  343. }
  344.  
  345. #ifdef AX25
  346. /* Display or change our AX.25 conference call */
  347. static
  348. doconfcall(argc,argv,p)
  349. int argc;
  350. char *argv[];
  351. void *p;
  352. {
  353.     char tmp[AXBUF];
  354.  
  355.     if(argc < 2){
  356.         tprintf(fullstrcr,pax25(tmp,Ccall));
  357.         return 0;
  358.     }
  359.     if(setcall(Ccall,argv[1]) == -1)
  360.         return -1;
  361.     return 0;
  362. }
  363.  
  364. int32 CT4init = 7200;   /* 2 hours default */
  365.  
  366. /* Set link redundancy timer */
  367. static
  368. doct4(argc,argv,p)
  369. int argc;
  370. char *argv[];
  371. void *p;
  372. {
  373.     return setlong(&CT4init,redun,argc,argv);
  374. }
  375. #endif /* AX25 */
  376.  
  377.  
  378. int CChannel = 0;    /* default entry to channel 0 */
  379.  
  380. /* Set entry channel number */
  381. static
  382. doentrychannel(argc,argv,p)
  383. int argc;
  384. char *argv[];
  385. void *p;
  386. {
  387.     return setint(&CChannel,entrystr,argc,argv);
  388. }
  389.  
  390.  
  391. /* Allow nets to be held on channel 0 */
  392. static
  393. doconvnet0(argc,argv,p)
  394. int argc;
  395. char *argv[];
  396. void *p;
  397. {
  398.     return setbool(&ConvNet0,allownets,argc,argv);
  399. }
  400.  
  401.  
  402. /* Allow broadcasts to be timestamped */
  403. static
  404. dotimestamp(argc,argv,p)
  405. int argc;
  406. char *argv[];
  407. void *p;
  408. {
  409.     return setbool(&TimeStamp,timestampstr,argc,argv);
  410. }
  411.  
  412.  
  413. static
  414. dociface(argc,argv,p)
  415. int argc;
  416. char *argv[];
  417. void *p;
  418. {
  419.     return(dosetflag(argc,argv,p,IS_CONV_IFACE, 1));
  420. }
  421.  
  422. int32 CMaxwait = MAX_WAITTIME;
  423.  
  424. /* Set maxwait time for timed out links */
  425. static int
  426. docmaxwait(argc,argv,p)
  427. int argc;
  428. char *argv[];
  429. void *p;
  430. {
  431.     return setlong(&CMaxwait,maxwaitstr,argc,argv);
  432. }
  433.  
  434. int HMaxQ = 5*1024L;
  435.  
  436. /* Set max qlimit for host links */
  437. static int
  438. dohmaxq(argc,argv,p)
  439. int argc;
  440. char *argv[];
  441. void *p;
  442. {
  443.     return setint(&HMaxQ,hostqueuestr,argc,argv);
  444. }
  445.  
  446. int UMaxQ = 1024L;
  447.  
  448. /* Set max qlimit for user links */
  449. static int
  450. doumaxq(argc,argv,p)
  451. int argc;
  452. char *argv[];
  453. void *p;
  454. {
  455.     return setint(&UMaxQ,userqueuestr,argc,argv);
  456. }
  457.  
  458. static
  459. dochostname(argc,argv,p)
  460. int argc;
  461. char *argv[];
  462. void *p;
  463. {
  464.     if(argc == 1)
  465.         tprintf(fullstrcr,Chostname);
  466.     else {
  467.         strncpy(Chostname,argv[1],NAMELEN);
  468.         Chostname[NAMELEN] = '\0';
  469.     }
  470.     return 0;
  471. }
  472.  
  473.  
  474. /*
  475. ** View/Change the message we send to new conference connects.
  476. */
  477.  
  478. static int doconfmotd(argc,argv,p)
  479. int argc;
  480. char *argv[];
  481. void *p;
  482. {
  483.     if (argc < 2)
  484.         tprintf(motdstr,confMOTD);
  485.     else
  486.     {
  487.         if (confMOTD != NULL) free(confMOTD);
  488.         confMOTD = malloc(strlen(argv[1]));
  489.         strcpy(confMOTD,argv[1]);
  490.     }
  491.     return 0;
  492. }
  493.  
  494. static int
  495. docfilter(argc,argv,p)
  496. int argc;
  497. char *argv[];
  498. void *p;
  499. {
  500.     int32 addr;
  501.     struct filter_link *fl;
  502.  
  503.     if(argc == 1) {
  504.         if(Filterlinks) {
  505.             tprintf(modeis, FilterMode ? acceptstr : refuse);
  506.             for(fl=Filterlinks;fl;fl=fl->next)
  507.                 tprintf(fullstrcr,inet_ntoa(fl->addr));
  508.         }
  509.         return 0;
  510.     }
  511.     if(!stricmp(argv[1],"mode")) {
  512.         if(argc == 2)
  513.             tprintf(modeis, FilterMode ? acceptstr : refuse);
  514.         else {
  515.             if(*argv[2] == 'a' || *argv[2] == 'A')
  516.                 FilterMode = 1;
  517.             else
  518.                 FilterMode = 0;
  519.         }
  520.         return 0;
  521.     }
  522.     if((addr = resolve(argv[1])) == 0) {
  523.         tprintf(Badhost,argv[1]);
  524.         return 1;
  525.     }
  526.     /* check to see if we already have this in the list */
  527.     for(fl=Filterlinks;fl;fl=fl->next)
  528.         if(fl->addr == addr)
  529.             return 0;       /* already have this one ! */
  530.  
  531.     /* Seems like a new one */
  532.     fl = (struct filter_link *)callocw(1,sizeof(struct filter_link));
  533.     fl->addr = addr;
  534.     fl->next = Filterlinks;
  535.     Filterlinks = fl;
  536.     return 0;
  537. }
  538.  
  539. #ifdef LINK
  540. static
  541. doclink(argc,argv,p)
  542. int argc;
  543. char *argv[];
  544. void *p;
  545. {
  546.     int32 addr;
  547.     struct permlink *pl;
  548.  
  549.     if(argc == 1) {
  550.         for(pl=permlinks;pl;pl=pl->next)
  551.             tprintf(fullstrcr,inet_ntoa(pl->addr));
  552.         return 0;
  553.     }
  554.     if((addr = resolve(argv[1])) == 0) {
  555.         tprintf(Badhost,argv[1]);
  556.         return 1;
  557.     }
  558.     /* check to see if we already have a link to such animal,
  559.      * this happens when we stop and restart the server - WG7J
  560.      */
  561.     for(pl=permlinks;pl;pl=pl->next)
  562.         if(pl->addr == addr)
  563.             return 1;       /* already have this one ! */
  564.  
  565.     /* Seems like a new link ! Go add it */
  566.     pl = (struct permlink *)callocw(1,sizeof(struct permlink ));
  567.     pl->addr = addr;
  568.     pl->next = permlinks;
  569.     permlinks = pl;
  570.     if(argc > 1) {
  571.         strncpy(pl->name,argv[2],NAMELEN);
  572.         update_permlinks(pl->name,NULLCONNECTION);
  573.     pl->retrytime -= 55;    /* 1st start in 5 seconds */
  574.     pl->waittime = 30;    /* 2nd after 1 minute */
  575.         
  576.     }
  577.     if(!Linker)
  578.         Linker = newproc("Clinker",1024,connect_permlinks,0,0,NULL,0);
  579.  
  580.     return 0;
  581. }
  582. #endif
  583.  
  584.  
  585. /* Stop convers server */
  586. int
  587. conv0(argc,argv,p)
  588. int argc;
  589. char *argv[];
  590. void *p;
  591. {
  592.     return (deleteserver (&Sconv));
  593. }
  594.  
  595. /* Start up convers server */
  596. int
  597. conv1(argc,argv,p)
  598. int argc;
  599. char *argv[];
  600. void *p;
  601. {
  602.     if (!Chostname[0])
  603.         strncpy (Chostname, Hostname, CNAMELEN);
  604.     installserver (argc, argv, &Sconv, "Conference listener", IPPORT_CONVERS,
  605.         conversd, conv_incom, 1024, NULL);
  606. #ifdef LINK
  607.     if (Linker)
  608.         killproc (Linker);
  609. #endif
  610.     return 0;
  611. }
  612.  
  613. static void
  614. free_connection(cp)
  615. register struct convection *cp;
  616. {
  617. register struct permlink *p;
  618.  
  619.     for (p = permlinks; p; p = p->next)
  620.             if (p->convection == cp)
  621.             p->convection = NULLCONNECTION;
  622.     free(cp->ibuf);
  623.         if(cp->flags & CLOSE_SOCK)
  624.             close_s(cp->fd);
  625.     free((char *) cp);
  626. }
  627.  
  628. static void
  629. free_closed_connections()
  630. {
  631. register struct convection *cp,*p;
  632. time_t currtime;
  633.  
  634.     currtime = time(&currtime);
  635.  
  636.     for(p = NULLCONNECTION,cp = convections; cp; )
  637.         if(cp->type == CT_CLOSED ||
  638.             cp->type == CT_UNKNOWN && cp->time + 300 < currtime) {
  639.             if(p) {
  640.                 p->next = cp->next;
  641.                 free_connection(cp);
  642.                 cp = p->next;
  643.             } else {
  644.                 convections = cp->next;
  645.                 free_connection(cp);
  646.                 cp = convections;
  647.             }
  648.         } else {
  649.             p = cp;
  650.             cp = cp->next;
  651.         }
  652. }
  653.  
  654. static void
  655. update_permlinks(name,cp)
  656. char  *name;
  657. struct convection *cp;
  658. {
  659. register struct permlink *p;
  660. time_t currtime;
  661.  
  662.     for(p = permlinks; p; p = p->next)
  663.         if(!strcmp(p->name,name)) {
  664.             currtime = time(&currtime);
  665.             p->convection = cp;
  666.             p->statetime = currtime;
  667.             p->tries = 0;
  668.             p->waittime = 60;
  669.             p->retrytime = currtime + p->waittime;
  670.         }
  671. }
  672.  
  673. static struct convection *
  674. alloc_connection(fd)
  675. int  fd;
  676. {
  677. register struct convection *cp;
  678. time_t currtime;
  679.  
  680.     currtime = time(NULL);
  681.  
  682.     cp = (struct convection *)callocw(1,sizeof(struct convection ));
  683.     cp->ibuf = (char *)callocw(1,LINELEN);
  684.     cp->fd = fd;
  685.     cp->maxq = UMaxQ;       /* Maximum qlimit for user */
  686.         cp->flags = CLOSE_SOCK+USE_SOUND;       /* close on exit, by default */
  687.     cp->time = currtime;
  688.     cp->next = convections;
  689.     cp->paged = -1;
  690.     cp->net = -1;
  691.     convections = cp;
  692.     return cp;
  693. }
  694.  
  695. #ifdef LINK
  696. /* check the host links for backlogged data.
  697.  * If larger then set threshold, kill the link.
  698.  * WG7J, 930208
  699.  */
  700. void check_buffer_overload(void) {
  701.     struct convection *p;
  702.  
  703.     /* check the size of the outstanding data buffers */
  704.     for(p = convections; p; p = p->next)
  705.         if((p->maxq != 0) && (socklen(p->fd,1) > p->maxq)) {
  706.                 /* Blow this one out of the water */
  707.                 shutdown(p->fd,2);
  708.                 close_s(p->fd);
  709.             }
  710. }
  711.  
  712. void
  713. connect_permlinks(a,b,c)
  714. int a;
  715. void *b;
  716. void *c;
  717. {
  718.     int s;
  719.     register struct permlink *p;
  720.     struct sockaddr_in cport;
  721.     time_t currtime;
  722.  
  723.     for(;;) {
  724.         mspause(15000L);
  725.         for(p = permlinks; p; p = p->next) {
  726.             currtime = time(&currtime);
  727.             if(p->convection || p->retrytime > currtime)
  728.                 continue;
  729.             p->tries++;
  730.             p->waittime <<= 1;
  731.                     if(p->waittime > CMaxwait)
  732.                         p->waittime = CMaxwait;
  733.             p->retrytime = p->waittime + currtime;
  734.             cport.sin_family = AF_INET;
  735.             cport.sin_port = IPPORT_CONVERS;
  736.             cport.sin_addr.s_addr = p->addr; /* we've resolved this earlier */
  737.             if((s = socket(AF_INET,SOCK_STREAM,0)) == -1)
  738.                 continue;
  739.             if(connect(s,(char *)&cport,SOCKSIZE) == -1) {
  740.                 shutdown(s,2);  /* to make sure it doesn't linger around */
  741.                 close_s(s);     /* WG7J - 9207228 */
  742.                 continue;
  743.             }
  744.             p->fd = s;
  745.             if(newproc("permlink",2048,conv_incom,s,0,NULL,0) == NULLPROC){
  746.                 shutdown(s,2);  /* blow it out of the water :-) */
  747.                 close_s(s);
  748.             }
  749.         }
  750.         check_buffer_overload();
  751.     }
  752. }
  753. #endif
  754.  
  755.  
  756. static void
  757. clear_locks()
  758. {
  759. register struct convection *p;
  760.  
  761.     for (p = convections; p; p = p->next)
  762.         p->locked = 0;
  763. }
  764.  
  765. static void send_sounds(p)
  766. struct convection *p;
  767. {
  768.     if(p->flags & USE_SOUND)
  769.         p->xmitted += usputs(p->fd,"");
  770. }
  771.  
  772. extern char *Months[];        /* in smtpserv.c */
  773.  
  774. static char *
  775. timestring(gmt)
  776. long  gmt;
  777. {
  778. static char  buffer[10];
  779. struct tm *tm;
  780. time_t currtime;
  781.  
  782.     currtime = time(&currtime);
  783.  
  784.  
  785.     tm = localtime(&gmt);
  786.     if(gmt + 24 * 60 * 60 > currtime)
  787.         sprintf(buffer,"%02d:%02d",tm->tm_hour,tm->tm_min);
  788.     else
  789.         sprintf(buffer,"%-3.3s %2d",Months[tm->tm_mon + 1],tm->tm_mday);
  790.     return buffer;
  791. }
  792.  
  793. static void
  794. send_user_change_msg(name,host,oldchannel,newchannel)
  795. char  *name,*host;
  796. int  oldchannel,newchannel;
  797. {
  798. register struct convection *p;
  799. time_t currtime;
  800. register struct group *gold, *gnew;
  801.  
  802.     currtime = time(&currtime);
  803.  
  804.     gold = find_group (oldchannel);
  805.     gnew = find_group (newchannel);
  806.     if(gold && gold->logfile)     {
  807.         if(newchannel >= 0)
  808.             fprintf(gold->logfile, theyswitched, stars,
  809.                  name,newchannel, timestring (currtime));
  810.         else
  811.             fprintf(gold->logfile,theysigned, stars, name, ff_str, timestring (currtime));
  812.         }
  813.     if (gnew && gnew->logfile)
  814.         fprintf(gnew->logfile,theysigned, stars, name, n_str, timestring (currtime));
  815.  
  816.     for(p = convections; p; p = p->next) {
  817.         if(p->type == CT_USER && !p->via && !p->locked) {
  818.             if(p->channel == oldchannel) {
  819.                 convcolorchange (p, SYSCOLORS);
  820.                 if(newchannel >= 0)
  821.                     p->xmitted += usprintf(p->fd, theyswitched, stars,
  822.                          name,newchannel, timestring (currtime));
  823.                 else
  824.                     p->xmitted += usprintf(p->fd,
  825.                         theysigned, stars, name, ff_str, timestring (currtime));
  826.                 p->locked = 1;
  827.             }
  828.             if(p->channel == newchannel) {
  829.                 convcolorchange (p, SYSCOLORS);
  830.                 send_sounds (p);
  831.                 p->xmitted += usprintf(p->fd,
  832.                     theysigned, stars, name, n_str, timestring (currtime));
  833.                 p->locked = 1;
  834.             }
  835.         }
  836.         if(p->type == CT_HOST && !p->locked) {
  837.             p->xmitted += usprintf(p->fd,huser,name,host,0,oldchannel,newchannel);
  838.             p->locked = 1;
  839.         }
  840.     }
  841. }
  842.  
  843. static char *
  844. formatline(prefix,text)
  845. char  *prefix,*text;
  846. {
  847.  
  848. #define PREFIXLEN 10
  849. #define CONVLINELEN   79
  850.  
  851. register char  *f,*t,*x;
  852. register int  l,lw;
  853. static char buf[2*LINELEN];
  854.  
  855.     for(f = prefix,t = buf; *f; *t++ = *f++) ;
  856.     l = (int)(t - buf);
  857.     f = text;
  858.     *t++ = ' ';
  859.     l++;
  860.  
  861.     for(;;) {
  862.         while(isspace(uchar(*f)))    {
  863. #ifndef NOSPACES
  864.             *t++ = *f;
  865.             l++;
  866. #endif
  867.             f++;
  868.             }
  869.         if(!*f)        {
  870.             *t++ = '\n';
  871.             *t = '\0';
  872.             return buf;
  873.             }
  874.         for (x = f; *x && !isspace(uchar(*x)); x++) ;
  875.         lw = (int)(x - f);
  876.         if(l > PREFIXLEN && l + 1 + lw > CONVLINELEN)    {
  877.             *t++ = '\n';
  878.             l = 0;
  879.             }
  880. #ifndef NOSPACES
  881.         while(l < PREFIXLEN)    {
  882. #else
  883.         do {
  884. #endif
  885.             *t++ = ' ';
  886.             l++;
  887. #ifndef NOSPACES
  888.         }
  889. #else
  890.         } while(l < PREFIXLEN);
  891. #endif
  892.         while(lw--) {
  893.             *t++ = *f++;
  894.             l++;
  895.         }
  896.     }
  897. }
  898.  
  899. static void
  900. send_msg_to_user(fromname,toname,text)
  901. char  *fromname,*toname,*text;
  902. {
  903. register struct convection *p;
  904.  
  905.     for(p = convections; p; p = p->next)         {
  906.         if(p->type == CT_USER && (!strcmpi(p->name,toname) || !strcmpi(p->nickname, toname)))
  907.             if(p->via)     {
  908.                 if(!p->via->locked)     {
  909.                     p->via->xmitted += usprintf(p->via->fd,
  910.                         umsgstr,fromname,toname,text);
  911.                     p->via->locked = 1;
  912.                     }
  913.             } else         {
  914.                 if(!p->locked)         {
  915.                     if(strcmp(fromname,conversd))     {
  916.                         char buffer[14+NAMELEN];
  917.                         time_t currtime;
  918.                         currtime = time(&currtime);
  919.                         convcolorchange (p, INFOCOLORS);
  920.                         sprintf(buffer,(TimeStamp) ? timestampfmt : nontimestampfmt,fromname, timestring(currtime));
  921.                         p->xmitted += usprintf(p->fd,fullstr,formatline(buffer,text));
  922.                     } else    {
  923.                         convcolorchange (p, SYSCOLORS);
  924.                         p->xmitted += usprintf(p->fd,fullstrcr,text);
  925.                     }
  926.                     p->locked = 1;
  927.                     }
  928.             }
  929.         }
  930. }
  931.  
  932. static void
  933. send_msg_to_channel(fromname,channel,text)
  934. char  *fromname;
  935. int  channel;
  936. char  *text;
  937. {
  938. char  buffer[7+NAMELEN];
  939. register struct convection *p;
  940. register struct group *gp;
  941. time_t currtime;
  942.  
  943.     currtime = time(&currtime);
  944.     sprintf(buffer,(TimeStamp) ? timestampfmt2 : nontimestampfmt2,fromname, timestring(currtime));
  945.     gp = find_group (channel);
  946.     if (gp && gp->logfile)
  947.         fprintf(gp->logfile,fullstr,(!strcmp (fromname,conversd)) ? text : formatline(buffer,text));
  948.  
  949.     for(p = convections; p; p = p->next) {
  950.         if(p->type == CT_USER && p->channel == channel)
  951.             if(p->via) {
  952.                 if(!p->via->locked) {
  953.                     p->via->xmitted += usprintf(p->via->fd,
  954.                     cmsgstr,fromname,channel,text);
  955.                     p->via->locked = 1;
  956.                 }
  957.             } else {
  958.                 if(!p->locked) {
  959.                     convcolorchange (p, TEXTCOLORS);
  960.                     p->xmitted += usprintf(p->fd,fullstr,
  961.                         (!strcmp (fromname,conversd)) ? text : formatline(buffer,text));
  962.                     p->locked = 1;
  963.                 }
  964.             }
  965.     }
  966. }
  967.  
  968.  
  969. static void
  970. send_invite_msg(fromname,toname,channel, msg)
  971. char  *fromname,*toname;
  972. int  channel;
  973. char  *msg;
  974. {
  975. char buffer[80];
  976. struct convection *p;
  977. #ifdef MAILBOX
  978. int i, yep = 0;
  979. struct mbx *m;
  980. #endif
  981. time_t currtime;
  982.  
  983.     currtime = time(&currtime);
  984.  
  985. #ifdef MAILBOX
  986.     if (!yep)    {  
  987.         for(i = 0; i < NUMMBX; i++){
  988.                 if((m = Mbox[i]) != NULLMBX){
  989.                     if(m->state == MBX_CMD && !stricmp(m->name,toname)) {
  990.                         (void) usprintf(m->user,mbinvitetext,amessage,fromname,timestring(currtime),stars,channel,channel);
  991.                 if (msg[0])
  992.                     usprintf (m->user, msgtext, fromname, msg);
  993.                         usflush(m->user);
  994.                         clear_locks();
  995.                         sprintf(buffer,responsetext,stars,toname,"BBS@");
  996.                         strcat(buffer,Hostname);
  997.                         send_msg_to_user(conversd,fromname,buffer);
  998.                         return;
  999.                         }
  1000.             }
  1001.         }
  1002.     }
  1003. #endif
  1004.  
  1005.     /* check the current convers users */
  1006.     for(p = convections; p; p = p->next) {
  1007.         if(p->type == CT_USER && !strcmpi(p->name,toname)) {
  1008.             if(p->channel == channel) {
  1009.                 clear_locks();
  1010.                 sprintf(buffer,alreadyon,stars,userstr,toname);
  1011.                 send_msg_to_user(conversd,fromname,buffer);
  1012.                 return;
  1013.             }
  1014.             if(!p->via && !p->locked) {
  1015.                 convcolorchange (p, INFOCOLORS);
  1016.                 p->paged = channel;
  1017.                         p->xmitted += usprintf(p->fd,invitetext,amessage,fromname, \
  1018.                                         timestring(currtime),stars,channel);
  1019.                 if (msg[0])
  1020.                     p->xmitted += usprintf (p->fd, msgtext, fromname, msg);
  1021.                         clear_locks();
  1022.                         sprintf(buffer,responsetext,stars,toname,Chostname);
  1023.                         send_msg_to_user(conversd,fromname,buffer);
  1024.                         return;
  1025.                         }    
  1026.             if(p->via && !p->via->locked) {
  1027.                 p->via->xmitted += usprintf(p->via->fd, hinvi,fromname,toname,channel, msg);
  1028.                 return;
  1029.             }
  1030.         }
  1031.     }
  1032.     /* Nothing found locally, invite user on all links */
  1033.     for(p = convections; p; p = p->next) {
  1034.         if(p->type == CT_HOST && !p->locked) {
  1035.             p->xmitted += usprintf(p->fd,hinvi,fromname,toname,channel, msg);
  1036.         }
  1037.     }
  1038. }
  1039.  
  1040.  
  1041.  
  1042. static void
  1043. time_command (cp)
  1044. struct  convection *cp;
  1045. {
  1046. time_t currtime;
  1047. char buff[24];
  1048.  
  1049.     currtime = time(&currtime);
  1050.     sprintf (buff, "%s%s is %s\n", stars,tmstr, timestring(currtime));
  1051.     clear_locks ();
  1052.     send_msg_to_channel(conversd,cp->channel,buff);
  1053. }
  1054.  
  1055.  
  1056. static int
  1057. onchannel (channel)
  1058. int channel;
  1059. {
  1060. int cnt = 0;
  1061. struct convection *p;
  1062.  
  1063.     for(p = convections; p; p = p->next)
  1064.         if(p->type == CT_USER && channel == p->channel)
  1065.             cnt++;
  1066.     return (cnt);
  1067. }
  1068.  
  1069. static void
  1070. bye_command(cp)
  1071. struct convection *cp;
  1072. {
  1073. register struct convection *p;
  1074.     
  1075.     if (cp->net != -1)    {
  1076.         int old = cp->channel;
  1077.         cp->channel = cp->net;
  1078.         nonet_command (cp);
  1079.         cp->channel = old;
  1080.     }
  1081.     switch(cp->type) {
  1082.     case CT_UNKNOWN:
  1083.         cp->type = CT_CLOSED;
  1084.         break;
  1085.     case CT_USER:
  1086.         cp->type = CT_CLOSED;
  1087.         convcolorchange (cp, SYSCOLORS);
  1088.         cp->xmitted += usprintf(cp->fd, exitingstr,conferencestr, Chostname);
  1089.         clear_locks();
  1090.         send_user_change_msg(cp->name,cp->host,cp->channel,-1);
  1091.         save_personal (cp);
  1092.         break;
  1093.     case CT_HOST:
  1094.         cp->type = CT_CLOSED;
  1095.         update_permlinks(cp->name,NULLCONNECTION);
  1096.         for (p = convections; p; p = p->next)
  1097.             if(p->via == cp)     {
  1098.                 p->type = CT_CLOSED;
  1099.                 clear_locks();
  1100.                 send_user_change_msg(p->name,p->host,p->channel,-1);
  1101.                 }
  1102.         break;
  1103.     case CT_CLOSED:
  1104.         break;
  1105.     }
  1106. }
  1107.  
  1108. static void
  1109. mystatus(cp, old)
  1110. struct convection *cp;
  1111. int old;
  1112. {
  1113. int  now;
  1114. struct group *gp;
  1115.  
  1116.     now = onchannel (cp->channel);
  1117.     cp->xmitted += usprintf(cp->fd,nowchannel,stars, channelstr, cp->channel, now, (now > 1) ? "s" : empty);
  1118.     gp = find_group (cp->channel);
  1119.     if (gp != NULLGROUP)    {
  1120.         convcolorchange (cp, SYSCOLORS);
  1121.         cp->xmitted += usprintf(cp->fd, welcome, stars, (gp->private) ? privatestr : empty,
  1122.             (gp->private) ? " " : empty, gp->name, netcontrolstr, gp->moderator, cp->nickname);
  1123.     }
  1124.     send_user_change_msg(cp->name,cp->host,old,cp->channel);
  1125. }
  1126.  
  1127. static void
  1128. channel_command(cp)
  1129. struct convection *cp;
  1130. {
  1131. char  s[7];
  1132. int  newchannel, oldchannel;
  1133.  
  1134.     s[0] = '\0';
  1135.     sscanf(cp->ibuf,"%*s %6s",s);
  1136.     if(s[0] == '\0')     {
  1137.         convcolorchange (cp, SYSCOLORS);
  1138.         cp->xmitted += usprintf(cp->fd,youare,stars,empty,cp->channel);
  1139.         return;
  1140.         }
  1141.     newchannel = atoi(s);
  1142. /*    if(newchannel < 0 || newchannel > MAXCHANNEL) {        */
  1143.     if(newchannel < 0)     {
  1144.         convcolorchange (cp, SYSCOLORS);
  1145.             cp->xmitted += usprintf(cp->fd,cnumber,MAXCHANNEL);
  1146.             return;
  1147.         }
  1148.     if(newchannel == cp->channel)         {
  1149.         convcolorchange (cp, SYSCOLORS);
  1150.             cp->xmitted += usprintf(cp->fd,youare,stars,"already ",cp->channel);
  1151.         return;
  1152.         }
  1153.     if (gatekeeper (cp, newchannel))
  1154.         return;
  1155.     oldchannel = cp->channel;
  1156.     cp->channel = newchannel;
  1157.     cp->nettime = time (&cp->nettime);
  1158.     cp->locked = 1;        /* for bump command    */
  1159.     mystatus (cp, oldchannel);
  1160. }
  1161.  
  1162.  
  1163. static void
  1164. accept_command(cp)
  1165. struct convection *cp;
  1166. {
  1167.     if (cp->paged == -1)    {
  1168.         convcolorchange (cp, SYSCOLORS);
  1169.         cp->xmitted += usprintf (cp->fd, "??? %s\n", channelstr);
  1170.     } else        {
  1171.         sprintf (cp->ibuf, "/c %d", cp->paged);
  1172.         channel_command (cp);
  1173.     }
  1174. }
  1175.  
  1176.  
  1177. static char *
  1178. skipone (cptr, times)
  1179. char *cptr;
  1180. int times;
  1181. {
  1182. int k;
  1183.     k = strlen (cptr) - 1;
  1184. #ifndef TNOS_68K
  1185.     if (cptr[k] == '\n')    {
  1186. #else
  1187.     if (cptr[k] == '\l')    {
  1188. #endif
  1189.         cptr[k] = 0;
  1190.         if (cptr[k - 1] == '\r')
  1191.             cptr[k - 1] = 0;
  1192.     }
  1193.     do    {
  1194.         while (*cptr && *cptr != ' ')
  1195.             cptr++;
  1196.         while (*cptr && *cptr == ' ')
  1197.             cptr++;
  1198.     } while (--times);
  1199.     return (cptr);
  1200. }
  1201.  
  1202. extern char *ConfNews;
  1203.  
  1204. static void
  1205. help_command(cp)
  1206. struct convection *cp;
  1207. {
  1208. int k;
  1209. char *cptr;
  1210. char *file2open;
  1211.  
  1212.     sockblock (cp->fd, SOCK_BLOCK);
  1213.     cptr = cp->ibuf;
  1214.     cptr = skipone (cptr, 1);
  1215.  
  1216.     file2open = (tolower (*cptr) != 'n') ? ConfHlp : (tolower(cptr[2]) == 'w') ? ConfNews: NetControlHlp;
  1217.     convcolorchange (cp, INFOCOLORS);
  1218.     k = DisplayFile (file2open,cp->fd);
  1219.     if (k)
  1220.         cp->xmitted += k;
  1221.     else    {
  1222.         convcolorchange (cp, SYSCOLORS);
  1223.         cp->xmitted += usprintf(cp->fd,noopenstr, file2open);
  1224.     }
  1225.     cp->xmitted += usprintf(cp->fd, trailer);    
  1226.     sockblock (cp->fd, SOCK_NOTXBLOCK);
  1227. }
  1228.  
  1229. static void
  1230. news_command(cp)
  1231. struct convection *cp;
  1232. {
  1233.     strcpy (cp->ibuf, "h news");
  1234.     help_command (cp);
  1235. }
  1236.  
  1237.  
  1238. static void
  1239. invite_command(cp)
  1240. struct convection *cp;
  1241. {
  1242. struct group *gp;
  1243. char toname[10], chk[4], *cptr, *cp2;
  1244. int k;
  1245.     
  1246.     chk[0] = toname[0] = '\0';
  1247.     sscanf(cp->ibuf,"%*s %16s %3s",toname, chk);
  1248.     cptr = chk;
  1249.     if (chk[0])    {
  1250.         cptr = cp->ibuf;
  1251.         cptr = skipone (cptr, 2);
  1252.         cptr[51] = 0;
  1253.         }
  1254.     if(*toname)        {
  1255.         if ((cp2 = strchr (toname, '@')) != NULLCHAR)
  1256.             cp2 = '\0';
  1257.         gp = find_group (cp->channel);
  1258.         if (gp && gp->private && cp->net != cp->channel)    {
  1259.             convcolorchange (cp, SYSCOLORS);
  1260.             cp->xmitted += usprintf (cp->fd, noinvite, stars,privatestr, netcontrolstr);
  1261.         } else
  1262.             send_invite_msg(cp->name,toname,cp->channel, cptr);
  1263.         }
  1264. }
  1265.  
  1266. static void
  1267. links_command(cp)
  1268. struct convection *cp;
  1269. {
  1270. char  tmp[20];
  1271. char full[3];
  1272. struct convection *pc;
  1273. struct permlink *pp;
  1274.  
  1275.     full[0] = '\0';
  1276.     convcolorchange (cp, INFOCOLORS);
  1277.  
  1278.     sscanf(cp->ibuf,"%*s %2s",full);
  1279.     cp->xmitted += usprintf(cp->fd,linkhdr,    (full[0] != 'l') ? empty : linkhdr2);
  1280.     for(pc = convections; pc; pc = pc->next)
  1281.         if(pc->type == CT_HOST) {
  1282.             cp->xmitted += usprintf(cp->fd,
  1283.                 (*full == 'l') ?
  1284.                 "%-16s %-12s  %s     %5d %7d %7d\n" :
  1285.                 "%-16s %-12s  %s\n",
  1286.                 pc->name,
  1287.                 "Connected",
  1288.                 timestring(pc->time),
  1289.                 0,    /* always 0, cuz NOS handles the tx-queue */
  1290.                 pc->received,
  1291.                 pc->xmitted);
  1292.         }
  1293.     for(pp = permlinks; pp; pp = pp->next)
  1294.         if(!pp->convection || pp->convection->type != CT_HOST) {
  1295.             strcpy(tmp,timestring(pp->retrytime)),
  1296.                 cp->xmitted += usprintf(cp->fd,
  1297.                 (*full == 'l') ?
  1298.                 "%-16s %-12s  %s   %s %5d\n" :
  1299.                 "%-16s %-12s  %s\n",
  1300.                 pp->name,
  1301.                 pp->convection ? "Connecting" : "Disconnected",
  1302.                 timestring(pp->statetime),
  1303.                 tmp,
  1304.                 pp->tries);
  1305.     }
  1306.     cp->xmitted += usprintf(cp->fd,trailer);
  1307. }
  1308.  
  1309. static void
  1310. msg_command(cp)
  1311. struct convection *cp;
  1312. {
  1313. char toname[NAMELEN+1],*text;
  1314. register struct convection *p;
  1315.  
  1316.     toname[0] = '\0';
  1317.     sscanf(cp->ibuf,"%*s %16s",toname);
  1318.     text = &cp->ibuf[0];
  1319.     text = skipone (text, 2);
  1320.  
  1321.     if(!*text)
  1322.         return;
  1323.     for(p = convections; p; p = p->next)
  1324.         if(p->type == CT_USER && (!strcmpi(p->name,toname) || !strcmpi(p->nickname,toname)))    {
  1325.             send_msg_to_user(cp->nickname,toname,text);
  1326.             return;
  1327.             }
  1328.     convcolorchange (cp, SYSCOLORS);
  1329.     cp->xmitted += usprintf(cp->fd,nosuchuser,stars,toname);
  1330. }
  1331.  
  1332. static void
  1333. announce_new_user (cp)
  1334. struct convection *cp;
  1335. {
  1336. char dummy[80];
  1337. register struct group *gp;
  1338. int numgroups;
  1339.  
  1340.     if (CountConfUsers() > 1)    {
  1341.         cp->xmitted += usprintf (cp->fd, online, stars, CountConfUsers());
  1342.         if ((numgroups = CountConfGroups()) != 0)
  1343.             cp->xmitted += usprintf (cp->fd, groupsavail, stars, (numgroups > 1) ? "are" : "is", (numgroups > 1) ? "s" : empty, numgroups);
  1344.     }
  1345.  
  1346.     sprintf (dummy, newuserstr, stars, cp->name, cp->channel);
  1347.     for (gp = groups; gp; gp = gp->next)
  1348.         if (gp->channel != cp->channel)
  1349.             send_msg_to_user (conversd, gp->moderator, dummy);
  1350. }
  1351.  
  1352.  
  1353. static void
  1354. color_command(cp)
  1355. struct convection *cp;
  1356. {
  1357. int  newchannel, now;
  1358. char dummy[8];
  1359.  
  1360.     sscanf(cp->ibuf,"%*s %6s",dummy);
  1361.     if (dummy)    {
  1362.         if (!stricmp (dummy, "on"))
  1363.             cp->flags |= USE_COLOR;
  1364.         if (!stricmp (dummy, "off"))
  1365.             cp->flags &= ~USE_COLOR;
  1366.     }
  1367.     
  1368.     cp->colorset[0] = '\0';
  1369.     convcolorchange (cp, SYSCOLORS);
  1370.     cp->xmitted += usprintf(cp->fd,colorstatus, stars, (cp->flags & USE_COLOR) ? n_str : ff_str);
  1371.     cp->flags |= CHANGED_INFO;
  1372. }
  1373.  
  1374.  
  1375. /* save the personal information for this user */
  1376. void save_personal(cp)
  1377. struct convection *cp;
  1378. {
  1379. FILE *old, *new;
  1380. char *newname;
  1381. int found = 0;
  1382.  
  1383.     if ((!cp->nickname[0] && !cp->data) || !(cp->flags & CHANGED_INFO))
  1384.         return;
  1385.     if((old = fopen(ConfInfo,UPDATE_TEXT)) == NULL)
  1386.         return;
  1387.     rewind (old);
  1388.     newname = (char *) malloc (strlen (ConfInfo) + 5);
  1389.     sprintf (newname, "%s.new", ConfInfo);
  1390.     if ((new = fopen(newname, CREATE_TEXT)) == NULLFILE)    {
  1391.         fclose (old);
  1392.         free (newname);
  1393.         return;
  1394.     }
  1395.     while (fgets(cp->ibuf,LINELEN,old) != NULLCHAR)    {
  1396.         rip (cp->ibuf);
  1397.         if (!stricmp (cp->ibuf, cp->name))    {
  1398.             found = 1;
  1399.             for ( ; ; )        {
  1400.                 fgets(cp->ibuf, LINELEN, old);
  1401.                 if (cp->ibuf[0] != ' ')        {
  1402. /*                    fputs (cp->ibuf, new);        */
  1403.                     break;
  1404.                 }
  1405.             }
  1406.             break;
  1407.         }
  1408.         fprintf (new, fullstrcr, cp->ibuf);
  1409.     }
  1410.     fprintf (new, fullstrcr, cp->name);
  1411.     if (cp->nickname)
  1412.         fprintf (new, " nickname %s\n", cp->nickname);
  1413.     if (cp->data)
  1414.         fprintf (new, " personal %s\n", cp->data);
  1415.     if (cp->flags & USE_COLOR)
  1416.         fprintf (new, " color ON\n");
  1417.     if (found)        /* add rest of file */
  1418.         do    {
  1419.             fputs (cp->ibuf, new);
  1420.         } while (fgets(cp->ibuf,LINELEN,old) != NULLCHAR);
  1421.     fclose (new);
  1422.     fclose (old);
  1423.     unlink (ConfInfo);
  1424.     rename (newname, ConfInfo);
  1425.     free (newname);
  1426.     return;
  1427. }
  1428.  
  1429. /* find the personal information for this user */
  1430. void set_personal(cp)
  1431. struct convection *cp;
  1432. {
  1433. FILE *fp;
  1434. char *cp1;
  1435.  
  1436.     if((fp = fopen(ConfInfo,READ_TEXT)) == NULL)
  1437.         return;
  1438.     while(fgets(cp->ibuf,LINELEN,fp) != NULL) {
  1439.         if (*(cp->ibuf) == ' ')
  1440.             continue;
  1441.         rip (cp->ibuf);
  1442.         if(stricmp(cp->name,cp->ibuf))
  1443.             continue;
  1444.         if (fgets(cp->ibuf,LINELEN,fp) != NULL) {
  1445.             if (!strnicmp (cp->ibuf, " nick", 5))    {
  1446.                 /* Found nickname data ! */
  1447.                 *(cp->ibuf) = '/';
  1448.                 nickname_command(cp);
  1449.                 fgets(cp->ibuf,LINELEN,fp);
  1450.             }
  1451.             if (!strnicmp (cp->ibuf, " pers", 5))    {
  1452.                 /* Found personal data ! */
  1453.                 *(cp->ibuf) = '/';
  1454.                 personal_command(cp);
  1455.                 fgets(cp->ibuf,LINELEN,fp);
  1456.             }
  1457.             if (!strnicmp (cp->ibuf, " color", 6))    {
  1458.                 /* Found color data ! */
  1459.                 *(cp->ibuf) = '/';
  1460.                 color_command(cp);
  1461.             }
  1462.             cp->xmitted += usprintf(cp->fd,welcomeback, stars, cp->nickname);
  1463.         }
  1464.     }
  1465.     fclose(fp);
  1466.         return;
  1467. }
  1468.  
  1469. static void
  1470. name_command(cp)
  1471. struct convection *cp;
  1472. {
  1473. int  newchannel, now;
  1474. char dummy[8];
  1475.  
  1476.     cp->name[0] = dummy[0] = '\0';
  1477.     sscanf(cp->ibuf,"%*s %16s %6s",cp->name,dummy);
  1478.     newchannel = atoi(dummy);
  1479.     if(!*cp->name)
  1480.         return;
  1481.     strcpy (cp->nickname, cp->name);
  1482.     strlwr(cp->name);
  1483.     strcpy(cp->host,Chostname);
  1484.     cp->type = CT_USER;
  1485.     cp->channel = (newchannel == -1) ? CChannel : newchannel;
  1486.  
  1487.     announce_new_user (cp);
  1488.     set_personal(cp);
  1489.     cp->flags &= ~CHANGED_INFO;
  1490.     mystatus (cp, (int) -1);
  1491. }
  1492.  
  1493. #ifdef LZW
  1494. /* Set or show the status of the 'compressed' flag - KO4KS */
  1495. static void
  1496. compressed_command(cp)
  1497. struct convection *cp;
  1498. {
  1499. char *cp2;
  1500. struct usock *up;
  1501.  
  1502.     if((cp2 = strchr(cp->ibuf,' ')) != NULLCHAR) {
  1503.         cp2++;
  1504.         if(*cp2 == 'o' || *cp2 == 'O') {   /* There is an argument */
  1505.             if(cp2[1] == 'f' || cp2[1] == 'F')    /* Turn it off */
  1506.                 cp->flags &= ~USE_LZW;
  1507.             else
  1508.                 cp->flags |= USE_LZW;
  1509.         up = itop(cp->fd);
  1510.             if ((cp->flags & USE_LZW) || (up->zout != NULLLZW))
  1511.             togglelzw (cp->fd, cp->flags & USE_LZW);
  1512.             
  1513.         }
  1514.     }
  1515.  
  1516.     convcolorchange (cp, SYSCOLORS);
  1517.     usprintf(cp->fd,"%sStream compression o%s\n", stars, (cp->flags & USE_LZW) ? n_str : ff_str);
  1518.     return;
  1519. }
  1520. #endif
  1521.  
  1522.  
  1523. /* Set or show the status of the 'sound' flag - WG7J */
  1524. static void
  1525. sounds_command(cp)
  1526. struct convection *cp;
  1527. {
  1528.     char *cp2;
  1529.  
  1530.     if((cp2 = strchr(cp->ibuf,' ')) != NULLCHAR) {
  1531.         cp2++;
  1532.         if(*cp2 == 'o' || *cp2 == 'O') {   /* There is an argument */
  1533.             if(cp2[1] == 'f' || cp2[1] == 'F')    /* Turn it off */
  1534.                 cp->flags &= ~USE_SOUND;
  1535.             else
  1536.                 cp->flags |= USE_SOUND;
  1537.         }
  1538.     }
  1539.  
  1540.     convcolorchange (cp, SYSCOLORS);
  1541.     usprintf(cp->fd,"%sSounds o%s\n", stars, (cp->flags & USE_SOUND) ? n_str : ff_str);
  1542.     return;
  1543. }
  1544.  
  1545. /* Send updated net data */
  1546. static void
  1547. update_net_data(gp)
  1548. struct group *gp;
  1549. {
  1550. struct convection *p;
  1551.         /* update all links */
  1552.         for(p=convections;p;p=p->next)
  1553.             if(p->type == CT_HOST)
  1554.                 p->xmitted += usprintf(p->fd,ndatstr,
  1555.                     gp->channel,gp->private,gp->logged,gp->nextq,gp->totalq,
  1556.             gp->name,gp->moderator,gp->password);
  1557. }
  1558.  
  1559.  
  1560. /* Send updated personal data, nickname, and password */
  1561. static void
  1562. update_user_data(cp)
  1563. struct convection *cp;
  1564. {
  1565. struct convection *p;
  1566.         /* update all links */
  1567.         for(p=convections;p;p=p->next)
  1568.             if(p->type == CT_HOST)
  1569.                 p->xmitted += usprintf(p->fd,udatstr,
  1570.                     cp->name,cp->host,cp->nickname, cp->net, cp->data ? cp->data : "~~");
  1571. }
  1572.  
  1573. /* Set some personal data, like name and qth - WG7J */
  1574. static void
  1575. personal_command(cp)
  1576. struct convection *cp;
  1577. {
  1578. struct convection *p;
  1579. char *cptr;
  1580.  
  1581.     cptr = cp->ibuf;
  1582.     cptr = skipone (cptr, 1);
  1583.     if(*cptr) {
  1584.         if(cp->data)
  1585.             free(cp->data);
  1586.         rip(cptr);      /* get rid of ending '\n' */
  1587.         cp->data = strdup(cptr);
  1588.         update_user_data (cp);
  1589.     cp->flags |= CHANGED_INFO;
  1590.     }
  1591.     convcolorchange (cp, SYSCOLORS);
  1592.     cp->xmitted += usprintf(cp->fd,personalset, stars, cp->data ? cp->data : empty );
  1593. }
  1594.  
  1595.  
  1596.  
  1597. static void
  1598. nickname_command(cp)
  1599. struct convection *cp;
  1600. {
  1601. int nonick = 0, err = 0;
  1602.  
  1603.     convcolorchange (cp, SYSCOLORS);
  1604.     if (tolower(cp->ibuf[2]) == 'o')    {
  1605.         nonick = 1;
  1606.         strcpy (cp->nickname, cp->name);
  1607.     }
  1608.     else        {
  1609.         char new[16];
  1610.         new[0] = '\0';
  1611.         sscanf(cp->ibuf,string15, new);
  1612.         if (*new)
  1613.             if (strcmp (new, systemstr))
  1614.                 strcpy (cp->nickname, new);
  1615.             else    {
  1616.                 cp->xmitted += usprintf(cp->fd,    nicknamestr, stars, nicknmstr, "can't be ", new);
  1617.                 err = 1;
  1618.             }
  1619.         }
  1620.     cp->xmitted += usprintf(cp->fd,    nicknamestr, stars, nicknmstr, (nonick) ? "re" : empty, cp->nickname);
  1621.     if (!err)
  1622.         update_user_data (cp);
  1623.     cp->flags |= CHANGED_INFO;
  1624. }
  1625.  
  1626.  
  1627. static void
  1628. password_command(cp)
  1629. struct convection *cp;
  1630. {
  1631. char new[16];
  1632.  
  1633.     convcolorchange (cp, SYSCOLORS);
  1634.     if (tolower(cp->ibuf[2]) == 'o')    {
  1635.         cp->password[0] = '\0';
  1636.         cp->xmitted += usprintf(cp->fd, "%s %s!\n", passwordstr, clearedstr);
  1637.         return;
  1638.     }
  1639.     new[0] = '\0';
  1640.     sscanf(cp->ibuf,string15,new);
  1641.     if (*new)    {
  1642.         strcpy (cp->password, new);
  1643.         cp->xmitted += usprintf(cp->fd, "%s%s is set!\n", stars, passwordstr);
  1644.         }
  1645.     else        {
  1646.         if (cp->password[0])
  1647.             cp->xmitted += usprintf(cp->fd, "%s%s is '%s'.\n", stars,
  1648.                 passwordstr, cp->password);
  1649.         else
  1650.             cp->xmitted += usprintf(cp->fd, "%sNo %s in use.\n", stars, passwordstr);
  1651.         }
  1652. }
  1653.  
  1654. int
  1655. isrosedigit (c)
  1656. char c;
  1657. {
  1658. int retval;
  1659.  
  1660.     retval = isdigit (c);
  1661.     if (!retval)
  1662.         switch (tolower (c))    {
  1663.             case 'l':
  1664.             case 'o':
  1665.             case 'i':    retval = 1;
  1666.                     break;
  1667.         }
  1668.     return retval;
  1669. }
  1670.  
  1671. static char *
  1672. getVia (call)
  1673. char *call;
  1674. {
  1675. char tmp[AXBUF];
  1676. static char roseaddr[14];
  1677. int i, k;
  1678. register struct ax_route *axr;
  1679.  
  1680.     roseaddr[0] = 0;
  1681.     for(axr = Ax_routes;axr != NULLAXR;axr = axr->next)    {
  1682.         pax25(tmp,axr->target);
  1683.         if (!strnicmp (call, tmp, strlen (call)))    {
  1684.             for (i = 0; i < axr->ndigis; i++)    {
  1685.                 pax25(tmp,axr->digis[i]);
  1686.                 if (strlen(tmp) != 6)
  1687.                     continue;
  1688.                 for (k = 0; k < 6; k++)    {
  1689.                     if (!isrosedigit(tmp[k]))
  1690.                         break;
  1691.                 }
  1692.                 if (k != 6)
  1693.                     continue;
  1694.                 sprintf (roseaddr, "ROSE <%-6.6s>", tmp);
  1695.                 return (roseaddr);
  1696.             }
  1697.             break;
  1698.         }
  1699.     }
  1700.     return (roseaddr);
  1701. }
  1702.  
  1703.  
  1704. /* this is called from the finger-daemon when 'conf' is fingered - WG7J */
  1705. int ShowConfUsers(s)
  1706. int s;
  1707. {
  1708. struct convection *p;
  1709. int cnt;
  1710.  
  1711.     cnt = usprintf (s, headerstr);
  1712.     for (p = convections; p; p = p->next)
  1713.             if (p->type == CT_USER)
  1714.             cnt += usprintf(s,userdata,p->name,p->host,p->via ? p->via->name : getVia(p->name),
  1715.                 p->channel,timestring(p->time),p->data ? p->data : empty);
  1716.     return (cnt);
  1717. }
  1718.  
  1719.  
  1720.  
  1721. int CountConfUsers()
  1722. {
  1723. struct convection *p;
  1724. int cnt = 0;
  1725.  
  1726.     for (p = convections; p; p = p->next)
  1727.             if (p->type == CT_USER)
  1728.             cnt++;
  1729.     return (cnt);
  1730. }
  1731.  
  1732.  
  1733. int CountConfGroups()
  1734. {
  1735. int cnt = 0;
  1736. register struct group *gp;
  1737.  
  1738.     for (gp = groups; gp; gp = gp->next)
  1739.         cnt++;
  1740.     return (cnt);
  1741. }
  1742.  
  1743.  
  1744. extern char *getquote __ARGS((void));
  1745.  
  1746. static void
  1747. quote_command(cp)
  1748. struct convection *cp;
  1749. {
  1750. char *p;
  1751.  
  1752.     p = getquote();
  1753.     if (p)    {
  1754.         clear_locks ();
  1755.         send_msg_to_channel(conversd,cp->channel,quotebanner);
  1756.         clear_locks ();
  1757.         send_msg_to_channel(conversd,cp->channel,p);
  1758.         clear_locks ();
  1759.         send_msg_to_channel(conversd,cp->channel,trailer);
  1760.         free (p);
  1761.     }
  1762. }
  1763.  
  1764.  
  1765. static void
  1766. who_command(cp)
  1767. struct convection *cp;
  1768. {
  1769. char buffer[80];
  1770. int channel,quick = 0, realname = 0;
  1771. struct convection *p;
  1772. char whois[16];
  1773. #ifdef MAILBOX
  1774. int i;
  1775. struct mbx *m;
  1776. #endif
  1777.  
  1778.     convcolorchange (cp, INFOCOLORS);
  1779.     whois[0] = buffer[0] = '\0';
  1780.     sscanf(cp->ibuf,"%*s %2s %15s",buffer, whois);
  1781.     switch(tolower(buffer[0])) {
  1782.     case 'q':
  1783.         quick = 1;
  1784.         break;
  1785.      case 'r':
  1786.         realname = 1;
  1787.         break;
  1788.     }
  1789.  
  1790.     if(quick) {
  1791.         cp->xmitted += usprintf(cp->fd,"%s  %ss\n", channelstr, userstr);
  1792.         clear_locks();
  1793.         do {
  1794.             channel = -1;
  1795.             for(p = convections; p; p = p->next) {
  1796.                 if(p->type == CT_USER &&
  1797.                   !p->locked &&
  1798.                   (channel < 0 || channel == p->channel)) {
  1799.                     if(channel < 0) {
  1800.                         channel = p->channel;
  1801.                         sprintf(buffer,"%7d ",channel);
  1802.                     }
  1803.                     strcat(buffer," ");
  1804.                     if (strlen (buffer) > 65)        {
  1805.                         cp->xmitted += usprintf(cp->fd,fullstrcr,buffer);
  1806.                         strcpy (buffer, "         ");
  1807.                     }
  1808.                     strcat(buffer,p->nickname);
  1809.                     p->locked = 1;
  1810.                 }
  1811.             }
  1812.             if(channel >= 0) {
  1813.                 cp->xmitted += usprintf(cp->fd,fullstrcr,buffer);
  1814.             }
  1815.         } while(channel >= 0);
  1816.     } else    if (realname)    {
  1817.         cp->xmitted += usprintf (cp->fd, whobanner, userstr, nicknmstr, channelstr);
  1818.         for (p = convections; p; p = p->next)        {
  1819.             if (p->type != CT_USER)
  1820.                 continue;
  1821.             if (!*whois || !strncmp (whois, p->nickname, strlen (whois)))
  1822.                 cp->xmitted += usprintf (cp->fd, "%-16.16s %-16.16s %7d %s\n",
  1823.                     p->name, p->nickname, p->channel, p->data ? p->data : empty);
  1824.             }
  1825.     } else {
  1826.         cp->xmitted += ShowConfUsers (cp->fd);
  1827.     }
  1828. #ifdef MAILBOX
  1829.     if (!realname)        {
  1830.         cp->xmitted += usprintf (cp->fd, "\nMailbox %ss\n", userstr);
  1831.         for(i = 0; i < NUMMBX; i++)
  1832.             if((m = Mbox[i]) != NULLMBX)
  1833.                 if(m->state == MBX_CMD) {
  1834.                     realname = 1;    /* we found one! */
  1835.                     if(quick)
  1836.                             cp->xmitted += usprintf(cp->fd," BBS %s\n",m->name);
  1837.                     else
  1838.                             cp->xmitted += usprintf(cp->fd,"%-16s BBS@%s\n",m->name,Hostname);
  1839.                     }
  1840.         if (!realname)
  1841.             cp->xmitted += usprintf(cp->fd,"(none)\n");
  1842.         }
  1843. #endif
  1844.     cp->xmitted += usprintf(cp->fd,trailer);
  1845. }
  1846.  
  1847.  
  1848. static void
  1849. realname_command(cp)
  1850. struct convection *cp;
  1851. {
  1852.     {
  1853.     char name[16];
  1854.  
  1855.         name[0] = '\0';
  1856.         sscanf (cp->ibuf, string15, name);
  1857.         sprintf (cp->ibuf, "/w r %s", name);
  1858.     }
  1859.     who_command (cp);
  1860. }
  1861.  
  1862.  
  1863. static void
  1864. h_cmsg_command(cp)
  1865. struct convection *cp;
  1866. {
  1867. char *text, *cptr;
  1868. int  channel;
  1869. char name[NAMELEN+1];
  1870.  
  1871.     sscanf (cp->ibuf, "%*s %16s %d |", name, &channel);
  1872.     text = &cp->ibuf[0];
  1873.     text = skipone (text, 3);
  1874.     text++;        /* skip the '|' */
  1875.     cptr = strrchr (text, '|');
  1876.     if (!cptr)
  1877.         return;        /* invalid CMSG */
  1878.     *cptr = 0;
  1879. /*    text[strlen(text) - 1] = 0;    */
  1880.     if (isprint (*text) != 0)
  1881.         send_msg_to_channel (name, channel, text);
  1882. }
  1883.  
  1884.  
  1885. /* Return 1 if the host is to be allowed, or 0 if refused - WG7J */
  1886. int Allow_host(int s) {
  1887.     struct filter_link *fl;
  1888.     struct sockaddr_in fsocket;
  1889.     int i = sizeof(struct sockaddr_in);
  1890.  
  1891.     if(Filterlinks) {    /* Check for this ip address */
  1892.         getpeername(s,(char *)&fsocket,&i);
  1893.         for(fl=Filterlinks;fl;fl=fl->next)
  1894.             if(fl->addr == fsocket.sin_addr.s_addr)
  1895.                 return FilterMode;
  1896.         /* Not found ! */
  1897.         return !FilterMode;
  1898.     }
  1899.     return 1;
  1900. }
  1901.  
  1902. static void
  1903. h_host_command(cp)
  1904. struct convection *cp;
  1905. {
  1906. char name[NAMELEN+1];
  1907. register struct convection *p;
  1908. register struct permlink *pp;
  1909. struct sockaddr_in fsocket;
  1910. int i = sizeof(struct sockaddr_in);
  1911.  
  1912.     if(!Allow_host(cp->fd)) {
  1913.         bye_command(cp);
  1914.         return;
  1915.     }
  1916.     name[0] = '\0';
  1917.     sscanf(cp->ibuf,"%*s %16s",name);
  1918.     if(name[0] == '\0') {
  1919.         bye_command(cp);
  1920.         return;
  1921.     }
  1922.     for(p = convections; p; p = p->next)
  1923.         if(!strcmp(p->name,name))    {
  1924.             bye_command(p);
  1925.             return;
  1926.         }
  1927.     for(pp = permlinks; pp; pp = pp->next)
  1928.         if(!strcmp(pp->name,name) && pp->convection && pp->convection != cp)    {
  1929.             bye_command((strcmp(Chostname,name) < 0) ? pp->convection : cp);
  1930.             return;
  1931.         }
  1932.     if(cp->type != CT_UNKNOWN)
  1933.         return;
  1934.     cp->type = CT_HOST;
  1935.     cp->maxq = HMaxQ;
  1936.     strcpy(cp->name,name);        /* already allocated */
  1937.     update_permlinks(name,cp);
  1938.     cp->xmitted += usprintf(cp->fd,hhoststr,Chostname);
  1939.     for(p = convections; p; p = p->next)
  1940.         if(p->type == CT_USER) {
  1941.             cp->xmitted += usprintf(cp->fd,huserstr,
  1942.                 p->name,p->host,0,-1,p->channel);
  1943.                     cp->xmitted += usprintf(cp->fd,udatstr,
  1944.                             p->name,p->host,p->nickname,p->net,p->data ? p->data : "~~");
  1945.         }
  1946. }
  1947.  
  1948.  
  1949. static void
  1950. h_invi_command(cp)
  1951. struct convection *cp;
  1952. {
  1953. char fromname[10],toname[10], msg[LINELEN];
  1954. int  channel;
  1955.  
  1956.     sscanf (cp->ibuf, "%*s %16s %16s %d %s", fromname, toname, &channel, msg);
  1957.     send_invite_msg (fromname, toname, channel, msg);
  1958. }
  1959.  
  1960.  
  1961. static void
  1962. h_loop_command(cp)
  1963. struct convection *cp;
  1964. {
  1965. char host[NAMELEN+1];
  1966.  
  1967.     sscanf (cp->ibuf, "%*s %s", host);
  1968.     log (cp->fd, "conversd rx: LOOP %s", host);
  1969.     bye_command (cp);
  1970. }
  1971.  
  1972.  
  1973. /* Command to take user's personal data across a link - WG7J */
  1974. void
  1975. h_udat_command(cp)
  1976. struct convection *cp;
  1977. {
  1978. char *name,*host,*data,*nickname,*channel;
  1979. struct convection *p;
  1980.  
  1981.     /* do a validity check first */
  1982.     if((name = strchr(cp->ibuf,' ')) == NULLCHAR)
  1983.         return;
  1984.     name++;
  1985.     if((host = strchr(name,' ')) == NULLCHAR)
  1986.         return;
  1987.     *host++ = '\0';
  1988.     if((nickname = strchr(host,' ')) == NULLCHAR)
  1989.         return;
  1990.     *nickname++ = '\0';
  1991.     if((channel = strchr(nickname,' ')) == NULLCHAR)
  1992.         return;
  1993.     *channel++ = '\0';
  1994.     if((data = strchr(channel,' ')) == NULLCHAR)
  1995.         return;
  1996.     *data++ = '\0';
  1997.     if (*data == '~' && data[1] == '~')
  1998.         *data = 0;
  1999.     else
  2000.         data[strlen(data) - 1] = 0;
  2001.     /* everything seems fine, now find user ! */
  2002.     for(p=convections;p;p=p->next)
  2003.         if(!strcmp(p->name,name) && !strcmp(p->host,host)) {
  2004.             strcpy (p->nickname, nickname);
  2005.             p->net = atoi (channel);
  2006.             if(strlen(data))    {
  2007.                 if(p->data)
  2008.                     free(p->data);
  2009.                 p->data = strdup(data);
  2010.                 }
  2011.             break;
  2012.         }
  2013. }
  2014.  
  2015.  
  2016. static void
  2017. initialusers (channel)
  2018. int channel;
  2019. {
  2020. register struct convection *p;
  2021.  
  2022.     for(p = convections; p; p = p->next)
  2023.         if(p->type == CT_USER && p->channel == channel)
  2024.             p->nettime = time(&p->nettime);
  2025. }
  2026.  
  2027.  
  2028. /* Command to take net's data across a link */
  2029. void
  2030. h_ndat_command(cp)
  2031. struct convection *cp;
  2032. {
  2033. char *name,*moderator,*password,*cptr;
  2034. struct group *p;
  2035. int channel, private, logged, nextq, totalq, madenew = 0;
  2036.  
  2037.     sscanf (cp->ibuf, "%*s %d %d %d %d %d", &channel, &private, &logged,
  2038.         &nextq, &totalq);
  2039.     cptr = cp->ibuf;
  2040.     cptr = skipone (cptr, 6);
  2041.     name = cptr;
  2042.     if((moderator = strchr(name,'|')) == NULLCHAR)
  2043.         return;
  2044.     *moderator++ = '\0';
  2045.     if((password = strchr(moderator,'|')) == NULLCHAR)
  2046.         return;
  2047.     *password++ = '\0';
  2048.     if((cptr = strchr(password, '|')) == NULLCHAR)
  2049.         return;
  2050.     *cptr = '\0';
  2051.     /* everything seems fine, now find net ! */
  2052.     p = find_group (channel);
  2053.     if (p == NULLGROUP)    {
  2054.         p = (struct group *)callocw (1, sizeof (struct group));
  2055.         p->next = groups;
  2056.         groups = p;
  2057.         p->channel = channel;
  2058.         madenew = 1;
  2059.         initialusers (channel);
  2060.     }
  2061.     p->private = private;
  2062.     p->logged = logged;
  2063.     p->nextq = nextq;
  2064.     p->totalq = totalq;
  2065.     strcpy (p->name, name);
  2066.     strcpy (p->moderator, moderator);
  2067.     strcpy (p->password, password);
  2068.     if (private == -1)        {    /* deleting net */
  2069.         cp->channel = channel;
  2070.         nonetoverride = 1;
  2071.         nonet_command (cp);
  2072.         madenew = 0;
  2073.     }
  2074.     if (madenew)    {
  2075.         char buf[100];
  2076.         sprintf (buf, activenetstr, stars, p->name);
  2077.         send_msg_to_channel (conversd, p->channel, buf);
  2078.     }        
  2079. }
  2080.  
  2081.  
  2082. /* Command to take net questions across a link */
  2083. void
  2084. h_ques_command(cp)
  2085. struct convection *cp;
  2086. {
  2087. char *name,*cptr;
  2088. struct group *p;
  2089. int channel;
  2090. char type;
  2091.  
  2092.     sscanf (cp->ibuf, "%*s %d %c %s", &channel, &type, &name);
  2093.     cptr = cp->ibuf;
  2094.     cptr = skipone (cptr, 4);
  2095.     p = find_group (channel);
  2096.     if (p != NULLGROUP && p->qfile)
  2097.         process_question (channel, type, name, cptr);
  2098. }
  2099.  
  2100.  
  2101. static void
  2102. h_umsg_command(cp)
  2103. struct convection *cp;
  2104. {
  2105. char fromname[NAMELEN+1],toname[NAMELEN+1],*text;
  2106.  
  2107.     sscanf(cp->ibuf,"%*s %16s %16s",fromname,toname);
  2108.     text = &cp->ibuf[0];
  2109.     text = skipone (text, 3);
  2110.     if(*text)
  2111.         send_msg_to_user(fromname,toname,text);
  2112. }
  2113.  
  2114.  
  2115. static void
  2116. h_bump_command(cp)
  2117. struct convection *cp;
  2118. {
  2119. char name[NAMELEN+1];
  2120. char channel[10];
  2121. register struct convection *p;
  2122. register struct group *gp;
  2123.  
  2124.     channel[0] = name[0] = 0;
  2125.     sscanf(cp->ibuf,"%*s %16s %s",name,channel);
  2126.     for(p = convections; p; p = p->next)
  2127.         if(p->type == CT_USER && !p->via && (!strcmpi(p->name,name) || !strcmpi(p->nickname, name)))    {
  2128.             sprintf (p->ibuf, "/c %s", channel);
  2129.             cp->locked = 0;
  2130.             channel_command (p);
  2131.             break;
  2132.             }
  2133. }
  2134.  
  2135.  
  2136. static void
  2137. h_user_command(cp)
  2138. struct convection *cp;
  2139. {
  2140. char host[NAMELEN+1],name[NAMELEN+1];
  2141. int  newchannel,oldchannel;
  2142. register struct convection *p;
  2143. time_t currtime;
  2144.  
  2145.     currtime = time(&currtime);
  2146.  
  2147.     sscanf(cp->ibuf,"%*s %16s %16s %*s %d %d",name,host,&oldchannel,&newchannel);
  2148.  
  2149.     for(p = convections; p; p = p->next)
  2150.         if(p->type == CT_USER) {
  2151.             /* new 920705 dl9sau */
  2152.             /* If Neighbour2 registers a user on HostX, while someone has already
  2153.              * been registered for HostX via Neighbour1, then we definitely have
  2154.              * a loop !  We send a loop detect message and then close the link:
  2155.              * /..LOOP <Chostname> <myneighbour> <host>
  2156.              *
  2157.              * The LOOP PREVENTION CODE detects ONLY a loop if it starts at this
  2158.              * host. That's, why I suggest this code to be implemented in every
  2159.              * conversd implementation.
  2160.              */
  2161.             if (oldchannel < 0 && p->via != cp && !stricmp(p->host, host)) {
  2162.                 usprintf(cp->fd,loopstr, Chostname, host,p->via ? p->via->name : Chostname);
  2163.                 log(cp->fd, "conversd sent: LOOP %s",host);
  2164.                 bye_command(cp);
  2165.                 return;
  2166.             }
  2167.             if(p->channel == oldchannel && p->via == cp && \
  2168.                 !strcmp(p->name,name) && !strcmp(p->host,host))
  2169.             break;
  2170.         }
  2171.     if(!p) {
  2172.         p = (struct convection *)callocw(1,sizeof(struct convection ));
  2173.         p->type = CT_USER;
  2174.         strcpy(p->name,name);
  2175.         strcpy(p->nickname,name); 
  2176.         strcpy(p->host,host);
  2177.         p->via = cp;
  2178.         p->channel = newchannel;
  2179.         p->time = currtime;
  2180.         p->next = convections;
  2181.         convections = p;
  2182.     }
  2183.     if((p->channel = newchannel) < 0)    {
  2184.         p->type = CT_CLOSED;
  2185.         free_closed_connections();  /*  VE3DTE Apr 5/93 */
  2186.     }
  2187.     send_user_change_msg(name,host,oldchannel,newchannel);
  2188. }
  2189.  
  2190.  
  2191. static struct group *
  2192. find_group (channel)
  2193. int channel;
  2194. {
  2195. register struct group *gp;
  2196.  
  2197.     for (gp = groups; gp; gp = gp->next)
  2198.         if (gp->channel == channel)
  2199.             return (gp);
  2200.     return (NULLGROUP);
  2201. }
  2202.  
  2203.  
  2204. static struct group *
  2205. get_group (cp)
  2206. struct convection *cp;
  2207. {
  2208. register struct group *gp;
  2209.  
  2210.     gp = find_group (cp->channel);
  2211.     if (gp == NULLGROUP)    {
  2212.         gp = (struct group *)callocw (1, sizeof (struct group));
  2213.         gp->next = groups;
  2214.         gp->channel = cp->channel;
  2215.         strcpy (gp->moderator, cp->name);
  2216.         strcpy (gp->password, cp->password);
  2217.         groups = gp;
  2218.         initialusers (cp->channel);
  2219.     }
  2220.     return (gp);
  2221. }
  2222.  
  2223.  
  2224. static struct group *
  2225. can_gcontrol (cp)
  2226. struct convection *cp;
  2227. {
  2228.     register struct group *g;
  2229.     if (cp->net != cp->channel)    {
  2230.         convcolorchange (cp, SYSCOLORS);
  2231.         cp->xmitted += usprintf (cp->fd, urnotstr, stars, netcontrolstr);
  2232.         return (NOCONTROL);
  2233.     }
  2234.     return (find_group (cp->channel));
  2235.     
  2236. }
  2237.  
  2238.  
  2239. static void
  2240. gname_command(cp, cptr)
  2241. struct convection *cp;
  2242. char *cptr;
  2243. {
  2244. register struct group *gp;
  2245.     
  2246.     convcolorchange (cp, SYSCOLORS);
  2247.     cptr = skipone (cptr, 1);
  2248.     gp = can_gcontrol (cp);
  2249.     if (gp == NOCONTROL)
  2250.         return;
  2251.     if (*cptr)    {
  2252.         char buf[100];
  2253.         strncpy (gp->name, cptr, 32);
  2254.         clear_locks ();
  2255.         sprintf (buf, activenetstr, stars, cptr);
  2256.         send_msg_to_channel (conversd, gp->channel, buf);
  2257.         update_net_data (gp);
  2258.         }
  2259.     else
  2260.         cp->xmitted += usprintf(cp->fd, activenetstr,stars,gp->name);
  2261. }
  2262.  
  2263.  
  2264. static void
  2265. assignnet_command(cp, cptr)
  2266. struct convection *cp;
  2267. char *cptr;
  2268. {
  2269. register struct convection *p;
  2270. register struct group *gp;
  2271.     
  2272.     convcolorchange (cp, SYSCOLORS);
  2273.     cptr = skipone (cptr, 1);
  2274.     if (cp->net == -1)    {
  2275.         cp->xmitted += usprintf (cp->fd, urnotstr, stars, netcontrolstr);
  2276.         return;
  2277.         }
  2278.     if (!*cptr)
  2279.         cp->xmitted += usprintf(cp->fd, nouserstr, unknownstr);
  2280.     else        {
  2281.         gp = find_group (cp->net);
  2282.         for(p = convections; p; p = p->next)     {
  2283.             if(p->type == CT_USER && (!strcmpi(p->name,cptr) || !strcmpi(p->nickname, cptr)))
  2284.                 break;
  2285.             }
  2286.         if (!p)        {
  2287.             cp->xmitted += usprintf(cp->fd, nouserstr, unknownstr);
  2288.             return;
  2289.             }
  2290.         if (p->net != -1)
  2291.             cp->xmitted += usprintf(cp->fd, busystr, sosorry, cptr, netcontrolstr);
  2292.         else    {
  2293.             char buf[80];
  2294.             p->net = cp->net;
  2295.             cp->net = -1;
  2296.             strcpy (gp->moderator, p->name);
  2297.             clear_locks ();
  2298.             sprintf (buf, urassigned, stars, cp->nickname, netcontrolstr, channelstr, gp->channel);
  2299.             send_msg_to_user (conversd, p->name, buf);    
  2300.             sprintf (buf, "%s'%s' is now %s\n", stars, p->nickname, netcontrolstr);
  2301.             if (p->net != cp->channel)
  2302.                 cp->xmitted += usprintf(cp->fd, buf);
  2303.             send_msg_to_channel (conversd, gp->channel, buf);
  2304.             update_user_data (p);
  2305.             update_user_data (cp);
  2306.             update_net_data (gp);
  2307.             }
  2308.         }
  2309. }
  2310.  
  2311.  
  2312.  
  2313. static void
  2314. bumpnet_command(cp, cptr)
  2315. struct convection *cp;
  2316. char *cptr;
  2317. {
  2318. register struct convection *p, *p2;
  2319. register struct group *gp;
  2320. char dummy[18];
  2321. int thischannel = 0;
  2322.     
  2323.     convcolorchange (cp, SYSCOLORS);
  2324.     dummy[0] = 0;
  2325.     sscanf (cptr, string15, dummy);
  2326.     cptr = skipone (cptr, 1);
  2327.     gp = can_gcontrol (cp);
  2328.     if (gp == NOCONTROL)
  2329.         return;
  2330.     if (!*cptr)
  2331.         cp->xmitted += usprintf(cp->fd, nouserstr, unknownstr);
  2332.     else        {
  2333.         for(p = convections; p; p = p->next)     {
  2334.             if(p->type == CT_USER && (!strcmpi(p->name,dummy) || !strcmpi(p->nickname, dummy)))
  2335.                 break;
  2336.             }
  2337.         if (!p)        {
  2338.             cp->xmitted += usprintf(cp->fd, nouserstr, unknownstr);
  2339.             return;
  2340.             }
  2341.         if (p->channel != cp->channel)
  2342.             cp->xmitted += usprintf(cp->fd, wrongchannel, stars, userstr, dummy, channelstr);
  2343.         else    {
  2344.             cptr = skipone (cptr, 1);
  2345.             thischannel = atoi (cptr);
  2346.             if (p->via)    {
  2347.                     for (p2 = convections; p2; p2 = p2->next)
  2348.                         if(p2->type == CT_HOST)
  2349.                             p2->xmitted += usprintf(p2->fd,bumpstr,p->name,thischannel);
  2350.                 }
  2351.             else        {
  2352.                 sprintf (p->ibuf, "/c %d\n", thischannel);
  2353.                 cp->locked = 0;
  2354.                 channel_command (p);
  2355.                 }
  2356.             }
  2357.         }
  2358. }
  2359.  
  2360. static void
  2361. process_question(channel, type, name, cptr)
  2362. int channel;
  2363. char type, *name, *cptr;
  2364. {
  2365. register struct group *gp;
  2366. struct convection *p;
  2367. char buf[LINELEN], nmbuf[32], tmbuf[10], nerf[60], *ptr;
  2368. int here, sendperm = 1;
  2369. time_t currtime;
  2370.  
  2371.     gp = find_group (channel);
  2372.     if (type == 'a')        {
  2373.         if (!gp->totalq && !gp->qfile)        {
  2374.             gp->qfile = tmpfile ();
  2375.             setbuf (gp->qfile, (char *) 0);
  2376.             }
  2377.         if (gp->qfile)        {
  2378.             gp->totalq++;
  2379.             update_net_data (gp);
  2380.             sendperm = 0;
  2381.             here = ftell (gp->qfile);
  2382.             fseek (gp->qfile, 0, SEEK_END);
  2383.             currtime = time(&currtime);
  2384.             fputs (name, gp->qfile);
  2385.             fputc ('\n', gp->qfile);
  2386.             fputs (timestring (currtime), gp->qfile);
  2387.             fputc ('\n', gp->qfile);
  2388.             fputs (cptr, gp->qfile);
  2389.             fputc (0, gp->qfile);
  2390.             fseek (gp->qfile, here, SEEK_SET);
  2391.             sprintf (buf, "%s from '%s'", questionstr, name);
  2392.             send_msg_to_user (conversd, gp->moderator, buf);
  2393.             }
  2394.         }
  2395.     else        {
  2396.         if (gp->qfile)        {
  2397.             sendperm = 0;
  2398.             here = ftell (gp->qfile);
  2399.             fgets (nmbuf, 16, gp->qfile);
  2400.             nmbuf[strlen(nmbuf) - 1] = 0;
  2401.             fgets (tmbuf, 9, gp->qfile);
  2402.             ptr = buf;
  2403.             do    {
  2404.                 *ptr = fgetc (gp->qfile);
  2405.             } while (*ptr++);
  2406.             if (type == 'p')    {
  2407.                 send_msg_to_user (nmbuf, gp->moderator, buf);
  2408.                 fseek (gp->qfile, here, SEEK_SET);
  2409.                 }
  2410.             else        {
  2411.                 gp->nextq++;
  2412.                 clear_locks ();
  2413.                 if (type != 's')    {
  2414.                     sprintf (nerf, "%sQuestion #%-d, sent by '%s' at%s", stars, gp->nextq, nmbuf, tmbuf);
  2415.                     send_msg_to_channel (conversd, gp->channel, nerf);
  2416.                     clear_locks ();
  2417.                     send_msg_to_channel (nmbuf, gp->channel, buf);
  2418.                     }
  2419.                 else    {
  2420.                     sprintf (nerf, "%sSkipped Question #%d",stars,gp->nextq);
  2421.                     send_msg_to_user (conversd, gp->moderator, nerf);
  2422.                     }
  2423.                 update_net_data (gp);
  2424.                 }
  2425.             }
  2426.         }
  2427.     if (sendperm)    {    /* qfile not local, send to remote links */
  2428.         for (p = convections; p; p = p->next)
  2429.             if(p->type == CT_HOST)
  2430.                 p->xmitted += usprintf(p->fd,quesstr,
  2431.                     channel, type, name, cptr);
  2432.     }
  2433. }
  2434.  
  2435. static void
  2436. question_command(cp, cptr)
  2437. struct convection *cp;
  2438. char *cptr;
  2439. {
  2440. register struct group *gp;
  2441. char type;
  2442.  
  2443.     cptr = skipone (cptr, 1);
  2444.     gp = find_group (cp->channel);
  2445.     if (gp == NULLGROUP)    {
  2446.         cp->xmitted += usprintf (cp->fd, nonetstr, stars);
  2447.         return;
  2448.     }
  2449.     cp->locked = 0;
  2450.     if (cp->net != cp->channel)    {    /* not net control */
  2451.         process_question (cp->channel, 'a', cp->nickname, cptr);
  2452.         cp->xmitted += usprintf (cp->fd, fullstrcr, questionstr);
  2453.         }
  2454.     else    {    /* options only available to net control */
  2455.         if (*cptr == '?')
  2456.             cp->xmitted += usprintf(cp->fd, "%s%d questions (%d unread)\n",stars,gp->totalq, gp->totalq - gp->nextq);
  2457.         else        { /* p=preview nc only, s=skip, other=display */
  2458.             if (!gp->totalq || !(gp->totalq - gp->nextq))    {
  2459.                 cp->xmitted += usprintf (cp->fd, "%sNone\n", stars);
  2460.                 return;
  2461.                 }
  2462.             type = tolower (*cptr);
  2463.             if (type != 'p' && type != 's')
  2464.                 type = 'r';
  2465.             process_question (cp->channel, type, cp->nickname, cptr);
  2466.         }
  2467.     }
  2468. }
  2469.  
  2470.  
  2471. static void
  2472. log_command(cp, cptr)
  2473. struct convection *cp;
  2474. char *cptr;
  2475. {
  2476. register struct group *gp;
  2477. int changed = 0;
  2478. time_t currtime;
  2479.  
  2480.     convcolorchange (cp, SYSCOLORS);
  2481.     currtime = time(&currtime);    
  2482.     cptr = skipone (cptr, 1);
  2483.     gp = can_gcontrol (cp);
  2484.     if (gp == NOCONTROL)
  2485.         return;
  2486.     if (gp->logfile)        {
  2487.         fprintf (gp->logfile, closeminutes, stars,timestring (currtime));
  2488.         fclose (gp->logfile);
  2489.         gp->logfile = (FILE *) 0;
  2490.         gp->logged = 0;
  2491.         changed = 1;
  2492.         cp->xmitted += usprintf(cp->fd, logfilestr, stars, "clos");
  2493.     }
  2494.     if (*cptr)    {
  2495.         gp->logfile = fopen (cptr, APPEND_TEXT);
  2496.         if (gp->logfile)    {
  2497.             fprintf (gp->logfile, openminutes, stars,timestring (currtime), stars, gp->name, netcontrolstr, gp->moderator);
  2498.             cp->xmitted += usprintf(cp->fd, logfilestr, stars, "open");
  2499.             gp->logged = 1;
  2500.             changed = 0;
  2501.             }
  2502.         else
  2503.             cp->xmitted += usprintf(cp->fd, noopenstr, cptr);
  2504.         }
  2505.     if (changed)
  2506.         update_net_data (gp);
  2507.     if (gp->logged)
  2508.         glog_command (cp);
  2509. }
  2510.  
  2511.  
  2512. static void
  2513. nonet_command(cp)
  2514. struct convection *cp;
  2515. {
  2516. register struct group *gp, *g;
  2517.     
  2518.     gp = can_gcontrol (cp);
  2519.     if (gp == NOCONTROL)    {
  2520.         if (!nonetoverride)
  2521.             return;
  2522.         else
  2523.             gp = find_group (cp->channel);
  2524.         }
  2525.  
  2526.     if (gp->qfile)
  2527.         fclose (gp->qfile);
  2528.     if (!nonetoverride)    {
  2529.         log_command (cp, empty);
  2530.         gp->private = -1;    /* indicator to remotes that we're done */
  2531.         update_net_data (gp);
  2532.         clear_locks ();
  2533.         send_msg_to_channel (conversd, gp->channel, "*** Net complete!\n");
  2534.         cp->net = -1;
  2535.         update_user_data (cp);
  2536.         }
  2537.     if (gp == groups)
  2538.         groups = gp->next;
  2539.     else    for (g = groups; g; g = g->next)
  2540.             if (g->next == gp)    {
  2541.                 g->next = gp->next;
  2542.                 break;
  2543.             }
  2544.     free (gp);            
  2545. }
  2546.  
  2547.  
  2548. static void
  2549. gpassword_command(cp, cptr)
  2550. struct convection *cp;
  2551. char *cptr;
  2552. {
  2553. char new[16];
  2554. register struct group *gp;
  2555.     
  2556.     convcolorchange (cp, SYSCOLORS);
  2557.     new[0] = '\0';
  2558.     sscanf(cptr,string15,new);
  2559.     gp = can_gcontrol (cp);
  2560.     if (gp == NOCONTROL)
  2561.         return;
  2562.     if (tolower (*cptr) == 'n')    {
  2563.         gp->password[0] = '\0';
  2564.         cp->xmitted += usprintf(cp->fd, net2str, stars, passwordstr, clearedstr);
  2565.         update_net_data (gp);
  2566.         return;
  2567.     }
  2568.     if (*new)    {
  2569.         strcpy (gp->password, new);
  2570.         cp->xmitted += usprintf(cp->fd, net2str, stars, passwordstr, "set");
  2571.         update_net_data (gp);
  2572.         }
  2573.     else        {
  2574.         if (gp->password[0])
  2575.             cp->xmitted += usprintf(cp->fd, "%sNet %s: '%s'.\n", stars,
  2576.                 passwordstr, gp->password);
  2577.         else
  2578.             cp->xmitted += usprintf(cp->fd, "%sNo Net %s\n", stars,passwordstr);
  2579.         }
  2580. }
  2581.  
  2582.  
  2583. static void
  2584. gprivate_command(cp, cptr)
  2585. struct convection *cp;
  2586. char *cptr;
  2587. {
  2588. struct group *gp;
  2589.     
  2590.     convcolorchange (cp, SYSCOLORS);
  2591.     gp = can_gcontrol (cp);
  2592.     if (gp != NOCONTROL)    {
  2593.         gp->private = (tolower (*cptr) == 'c') ? 1 : 0;
  2594.         cp->xmitted += usprintf(cp->fd, "%sNet no%s %s\n", stars,
  2595.             (gp->private) ? "w" : "t", privatestr);
  2596.         update_net_data (gp);
  2597.     }
  2598. }
  2599.  
  2600.  
  2601. static void
  2602. group_command(cp, cptr)
  2603. struct convection *cp;
  2604. char *cptr;
  2605. {
  2606. struct group *p;
  2607.  
  2608.     convcolorchange (cp, SYSCOLORS);
  2609.     if (groups == NULLGROUP)
  2610.         cp->xmitted += usprintf(cp->fd,"%sNo Active Nets!\n", stars);
  2611.     else        {
  2612.         cp->xmitted += usprintf(cp->fd,"%s  Net Topic\n", channelstr);
  2613.         for(p = groups; p; p = p->next)
  2614.             cp->xmitted += usprintf(cp->fd,"%7d  %-32s <%s>\n",p->channel, p->name, p->moderator);
  2615.         cp->xmitted += usprintf(cp->fd,trailer);
  2616.         }
  2617. }
  2618.  
  2619.  
  2620. static long seed = 1L;
  2621. #define CONV_RAND_MAX 0x7fffffff
  2622.  
  2623. static int
  2624. conv_rand()
  2625. {
  2626.     seed = (1103515245L * seed + 12345) & CONV_RAND_MAX;
  2627.     return((int) (seed & 077777));
  2628. }
  2629.  
  2630. static void
  2631. conv_randomize()
  2632. {
  2633.     seed = (time (0) & CONV_RAND_MAX);
  2634. }
  2635.  
  2636. static int
  2637. conv_random(num, base)
  2638. int num, base;
  2639. {
  2640.     return (((long)conv_rand() % num) + base);
  2641. }
  2642.  
  2643. static char DFAR *suits[] = {"Hearts", "Clubs", "Diamonds", "Spades"};
  2644. static char DFAR *cards[] = {"Ace", "Deuce", "Three", "Four", "Five", "Six",
  2645.             "Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King"};
  2646.  
  2647.  
  2648. extern char *SMILEYFile;
  2649.  
  2650. static void
  2651. smiley_command(cp)
  2652. struct convection *cp;
  2653. {
  2654. int offset, k;
  2655. char buff[200];
  2656. FILE *fp;
  2657.  
  2658.     conv_randomize();
  2659.     offset = conv_random (817, 1);
  2660.     if (!(fp = fopen (SMILEYFile, "r")))
  2661.         return;
  2662.     sprintf (buff, "%sSmiley: ", stars);
  2663.     for (k = 0; k < offset; k++)
  2664.         fgets (&buff[12], 188, fp);
  2665.      clear_locks ();
  2666.     send_msg_to_channel(conversd,cp->channel,buff);
  2667. }
  2668.  
  2669.  
  2670. #ifdef SAMCALLB
  2671. extern int SAMoutbytes;
  2672.  
  2673. static void
  2674. call_command(cp)
  2675. struct convection *cp;
  2676. {
  2677. char buff[16];
  2678. int k;
  2679.  
  2680.     buff[0] = 0;
  2681.     sscanf(cp->ibuf, string15, buff);
  2682.     if (*buff)    {
  2683.         k = cb_lookup (cp->fd, buff, (FILE *) 0);
  2684.         if (SAMoutbytes)    {
  2685.             cp->xmitted += SAMoutbytes;
  2686.             if (k != 2)
  2687.                 cp->xmitted += usprintf(cp->fd,trailer);
  2688.         } else
  2689.             cp->xmitted += usprintf(cp->fd, "%sCallbook server not active at %s\n", stars, Hostname);
  2690.     } else
  2691.         cp->xmitted += usprintf(cp->fd, "%sNo callsign given\n", stars);
  2692. }
  2693. #endif
  2694.  
  2695.  
  2696. static void
  2697. roll_command(cp)
  2698. struct convection *cp;
  2699. {
  2700. int die1, die2;
  2701. char buff[80];
  2702.  
  2703.     conv_randomize();
  2704.     die1 = conv_random (6, 1);
  2705.     die2 = conv_random (6, 1);
  2706.      clear_locks ();
  2707.     sprintf (buff, rollstr, stars, cp->nickname, die1, die2, die1+die2, trailer);
  2708.     send_msg_to_channel(conversd,cp->channel,buff);
  2709. }
  2710.  
  2711.  
  2712. static void
  2713. cut_command(cp)
  2714. struct convection *cp;
  2715. {
  2716. int die1, die2;
  2717. char buff[80];
  2718.  
  2719.     conv_randomize();
  2720.     die1 = conv_random (4, 0);
  2721.     die2 = conv_random (13, 0);
  2722.      clear_locks ();
  2723.     sprintf (buff, cutstr, stars, cp->nickname, cards[die2], suits[die1], trailer);
  2724.     send_msg_to_channel(conversd,cp->channel,buff);
  2725. }
  2726.  
  2727.  
  2728. static void
  2729. glog_command(cp)
  2730. struct convection *cp;
  2731. {
  2732. char buffer[75];
  2733. struct convection *p;
  2734. struct group *gp;
  2735.  
  2736.     gp = can_gcontrol (cp);
  2737.     if (gp == NOCONTROL)
  2738.         return;
  2739.      clear_locks ();
  2740.     send_msg_to_channel (conversd, gp->channel, gloghdr);
  2741.      clear_locks ();
  2742.      sprintf (buffer, glogstr, userstr, nicknmstr, hoststr);
  2743.     send_msg_to_channel (conversd, gp->channel, buffer);
  2744.     for(p = convections; p; p = p->next)
  2745.         if(p->type == CT_USER && gp->channel == p->channel)    {
  2746.             sprintf (buffer, "    %-8.8s %-15.15s  %s  %-30.30s\n", p->name,
  2747.                 p->nickname, timestring (p->nettime), p->host);
  2748.             clear_locks ();
  2749.             send_msg_to_channel (conversd, gp->channel, buffer);
  2750.             }
  2751.      clear_locks ();
  2752.     send_msg_to_channel (conversd, gp->channel, trailer);
  2753. }
  2754.  
  2755.  
  2756. static void
  2757. net_command(cp)
  2758. struct convection *cp;
  2759. {
  2760. char *cptr;
  2761. register struct group *gp;
  2762.     
  2763.     convcolorchange (cp, SYSCOLORS);
  2764.     cptr = cp->ibuf;
  2765.     cptr = skipone (cptr, 1);
  2766.     if (!cp->channel && !ConvNet0 && (tolower (*cptr) == 's'))    {
  2767.         cp->xmitted += usprintf(cp->fd, "%sNo nets on %s 0\n", stars, channelstr);
  2768.         return;
  2769.         }
  2770.     gp = find_group (cp->channel);
  2771.     switch (tolower (*cptr))    {
  2772.         case 0:        group_command (cp, cptr);
  2773.                 break;
  2774.         case 'c':    if (tolower (cptr[1]) == 'o')    {
  2775.                     if (gp == NULLGROUP)
  2776.                         cp->xmitted += usprintf(cp->fd, nonetstr, stars);
  2777.                     else
  2778.                         cp->xmitted += usprintf(cp->fd, "%s is '%s'.\n", netcontrolstr,
  2779.                             gp->moderator);
  2780.                     }
  2781.                 else
  2782.                     gprivate_command (cp, cptr);
  2783.                 break;
  2784.         case 'r':    if (gp == NULLGROUP)
  2785.                     cp->xmitted += usprintf(cp->fd, nonetstr, stars);
  2786.                 else    {
  2787.                     char new[75];
  2788.                     cp->xmitted += usprintf(cp->fd, fullstrcr,recheckstr);
  2789.                     sprintf (new, "%s: %s", recheckstr, cp->nickname);
  2790.                     send_msg_to_user (conversd, gp->moderator, new);
  2791.                     }
  2792.                 break;    
  2793.         case 'o':    gprivate_command (cp, cptr);
  2794.                 break;
  2795.         case 'l':    glog_command (cp);
  2796.                 break;
  2797.         case 'i':    if (cp->net != -1)    {
  2798.                     if (cp->net != cp->channel)
  2799.                         gp = find_group (cp->net);
  2800.                     cp->xmitted += usprintf(cp->fd, "%sYou are %s on %s %d\n", stars, netcontrolstr, channelstr,gp->channel);
  2801.                     gname_command (cp, empty);
  2802.                     cp->xmitted += usprintf(cp->fd, "%sNet is %s and the minutes are %sbeing recorded\n", stars,
  2803.                         gp->private ? "closed" : "open", gp->logged ? empty : "not ");
  2804.                     gpassword_command (cp, empty);
  2805.                     question_command (cp, "q ?");
  2806.                     }
  2807.                 else    glog_command (cp);    /* prints my error msg */
  2808.                 break; 
  2809.         case 't':    gname_command (cp, cptr);
  2810.                 break;
  2811.         case 'm':    log_command (cp, cptr);
  2812.                 break;
  2813.         case 'e':    nonet_command (cp);
  2814.                 break;
  2815.         case 'a':    assignnet_command (cp, cptr);
  2816.                 break;
  2817.         case 'b':    bumpnet_command (cp, cptr);
  2818.                 break;
  2819.         case 'w':    cptr = skipone (cptr, 1);
  2820.                 if (gp == NULLGROUP)
  2821.                     cp->xmitted += usprintf(cp->fd, nonetstr, stars);
  2822.                 else
  2823.                     send_msg_to_user (cp->nickname, gp->moderator, cptr);
  2824.                 break;
  2825.         case 'q':    question_command (cp, cptr);
  2826.                 break;
  2827.         case '?':
  2828.         case 'h':    strcpy (cp->ibuf, "h net");
  2829.                 help_command (cp);
  2830.                 break;
  2831.         case 'n':
  2832.         case 'p':    gpassword_command (cp, cptr);
  2833.                 break;
  2834.         case 's':    if (cp->net != -1)    {
  2835.                     cp->xmitted += usprintf(cp->fd, "%sAlready a %s\n", stars, netcontrolstr);
  2836.                     return;
  2837.                     }
  2838.                 
  2839.                 if (gp != NULLGROUP)    {
  2840.                     cp->xmitted += usprintf(cp->fd, "%sThere's a %s\n", stars, netcontrolstr);
  2841.                     return;
  2842.                     }
  2843.                 gp = get_group (cp);
  2844.                 cp->net = cp->channel;
  2845.                 update_user_data (cp);
  2846.                 gname_command (cp, cptr);
  2847.                 break;
  2848.         default:    cp->xmitted += usprintf(cp->fd,unkcmdstr,unknownstr, cptr, gethelpstr);
  2849.         }
  2850.  
  2851. }
  2852.  
  2853.  
  2854. static struct group *
  2855. lookup_group (name)
  2856. char *name;
  2857. {
  2858. register struct group *gp;
  2859.  
  2860.     for (gp = groups; gp; gp = gp->next)
  2861.         if (!strnicmp(gp->name, name, strlen (name)))
  2862.             return (gp);
  2863.     return (NULLGROUP);
  2864. }
  2865.  
  2866.  
  2867.  
  2868. static void
  2869. list_groups_command (cp)
  2870. struct convection *cp;
  2871. {
  2872. register struct group *gp;
  2873. struct convection *p;
  2874. int cnt;
  2875.  
  2876.     cp->xmitted += usprintf (cp->fd, grouphdr, stars);
  2877.     for (gp = groups; gp; gp = gp->next)    {
  2878.         cnt = 0;
  2879.         for (p = convections; p; p = p->next)    {
  2880.                 if ((p->type == CT_USER) && (p->channel == gp->channel))
  2881.                 cnt++;
  2882.         }
  2883.         cp->xmitted += usprintf (cp->fd, "   %5d  %-34.34s  (%02d user%s  %9s  %s\n", gp->channel,
  2884.             gp->name, cnt, (cnt > 1) ? "s)" : ") ", gp->private ? "[PRIVATE]" : empty,
  2885.             gp->password[0] ? "[PASSWORD]" : empty);
  2886.     }
  2887.     cp->xmitted += usprintf(cp->fd,trailer);
  2888. }
  2889.  
  2890.  
  2891.  
  2892. static void
  2893. join_command(cp)
  2894. struct convection *cp;
  2895. {
  2896. char s[36];
  2897. register struct group *gp;
  2898. int k, old;
  2899.  
  2900.     s[0] = '\0';
  2901.     sscanf(cp->ibuf,"%*s %34s",s);
  2902.     if (!s)
  2903.         return;
  2904.     if ((gp = lookup_group(s)) == NULLGROUP)    {
  2905.         old = cp->channel;
  2906.         for (k = 1; k < MAXCHANNEL; k++)    {
  2907.             if ((gp = find_group (k)) == NULLGROUP)
  2908.                 break;
  2909.         }
  2910.         cp->channel = k;
  2911.         gp = get_group (cp);
  2912.         cp->net = cp->channel;
  2913.         update_user_data (cp);
  2914.         gname_command (cp, cp->ibuf);
  2915.         cp->channel = old;
  2916.     }
  2917.     sprintf (cp->ibuf, "/c %d", gp->channel);
  2918.     channel_command (cp);
  2919. }
  2920.  
  2921.  
  2922. static int
  2923. gatekeeper (cp, channel)
  2924. struct convection *cp;
  2925. int channel;
  2926. {
  2927. register struct group *gp;
  2928. char buf[40];
  2929.  
  2930.     gp = find_group (channel);
  2931.     if (gp == NULLGROUP)
  2932.         return (0);        /* okay, there's no net control */
  2933.     if (cp->paged == channel)    {    /* we were invited! */
  2934.         cp->paged = -1;
  2935.         return (0);
  2936.     }
  2937.     if (cp->net == channel)        /* we control the net */
  2938.         return (0);
  2939.     sprintf (buf, "%s'%s' tried to join", stars, cp->name);
  2940.     if (gp->private)    {
  2941.         cp->xmitted += usprintf (cp->fd, sorry, sosorry, privatestr, channelstr, channel);
  2942.         send_msg_to_user (conversd, gp->moderator, buf);
  2943.         return (1);
  2944.     }
  2945.     if (gp->password[0])
  2946.         if (strcmpi (cp->password, gp->password))    {
  2947.             cp->xmitted += usprintf (cp->fd, sorry, sosorry, passwordstr, channelstr, channel);
  2948.             send_msg_to_user (conversd, gp->moderator, buf);
  2949.             return (1);
  2950.         }
  2951.     return (0);            
  2952. }
  2953.  
  2954. struct cmdtable {
  2955.     char  *name;
  2956.     void (*fnc)();
  2957.     int  states;
  2958.     } DFAR cmdtable[] = {
  2959.         "?",        cmdsummary_command,    CM_USER,
  2960.         "accept",    accept_command,        CM_USER,
  2961.         "bye",        bye_command,        CM_USER,
  2962.         "channel",    channel_command,    CM_USER,
  2963. #ifdef SAMCALLB
  2964.         "call",        call_command,        CM_USER,
  2965. #endif
  2966.         "color",    color_command,        CM_USER,
  2967. #ifdef LZW
  2968.         "compressed",   compressed_command,    CM_USER,
  2969. #endif
  2970.         "cut",        cut_command,        CM_USER,
  2971.         "exit",        bye_command,        CM_USER,
  2972.         "groups",    list_groups_command,    CM_USER,
  2973.         "help",        help_command,        CM_USER,
  2974.         "invite",    invite_command,        CM_USER,
  2975.         "join",        join_command,        CM_USER,
  2976.         "links",    links_command,        CM_USER,
  2977.         "msg",        msg_command,        CM_USER,
  2978.         "net",        net_command,        CM_USER,
  2979.         "name",        name_command,        CM_UNKNOWN,
  2980.         "news",        news_command,        CM_USER,
  2981.         "nickname",    nickname_command,    CM_USER,
  2982.         "nonickname",   nickname_command,    CM_USER,
  2983.         "nopassword",    password_command,    CM_USER,
  2984.         "page",        invite_command,        CM_USER,
  2985.         "password",    password_command,    CM_USER,
  2986.         "personal",    personal_command,    CM_USER,
  2987.         "quit",        bye_command,        CM_USER,
  2988.         "quote",    quote_command,        CM_USER,
  2989.         "realname",     realname_command,    CM_USER,
  2990.         "roll",        roll_command,        CM_USER,
  2991.         "send",        msg_command,        CM_USER,
  2992.         "smiley",    smiley_command,        CM_USER,
  2993.         "sounds",    sounds_command,        CM_USER,
  2994.         "time",        time_command,        CM_USER,
  2995.         "who",        who_command,        CM_USER,
  2996.         "write",    msg_command,        CM_USER,
  2997.  
  2998.         "\377\200bump", h_bump_command,        CM_HOST,
  2999.         "\377\200cmsg", h_cmsg_command,        CM_HOST,
  3000.         "\377\200host", h_host_command,        CM_UNKNOWN,
  3001.         "\377\200invi", h_invi_command,        CM_HOST,
  3002.         "\377\200loop", h_loop_command,        CM_HOST,
  3003.         "\377\200ndat", h_ndat_command,        CM_HOST,
  3004.         "\377\200ques", h_ques_command,        CM_HOST,
  3005.         "\377\200udat", h_udat_command,        CM_HOST,
  3006.         "\377\200umsg", h_umsg_command,        CM_HOST,
  3007.         "\377\200user", h_user_command,        CM_HOST,
  3008.         0,        0,            0,
  3009.     };
  3010.  
  3011.  
  3012. static void
  3013. process_commands(cp,m)
  3014. struct convection *cp;
  3015. struct mbx *m;
  3016. {
  3017. char arg[40];
  3018. int arglen,size;
  3019. int firstcmd = 1;
  3020. char *ccp;
  3021. struct cmdtable *cmdp;
  3022.  
  3023.     Conflogins++;
  3024.     if (m)
  3025.         firstcmd = 0;
  3026.     if (m == (struct mbx *) 1)
  3027.         m = NULLMBX;
  3028.     if (confMOTD != NULL)
  3029.         cp->xmitted += usprintf(cp->fd, "\n%s\n", confMOTD);
  3030.     for (;;)     {
  3031. loop:
  3032.         if (m)    {
  3033.             usflush (cp->fd);    /* might not be neccesary */
  3034. #ifdef MBXTDISC
  3035.             /* Restart the inactivity timer - WG7J */
  3036.             start_timer(&m->tdisc);
  3037. #endif
  3038.         }
  3039.         if (cp->type == CT_CLOSED)
  3040.             break;
  3041.         memset (cp->ibuf, 0, LINELEN);
  3042.         if((size = recvline (cp->fd, cp->ibuf, LINELEN-1)) <= 0)
  3043.             break;
  3044.         cp->received += size;
  3045.         clear_locks ();
  3046.         cp->locked = 1;
  3047.         if (*cp->ibuf == '/')     {
  3048.             ccp = &cp->ibuf[1];
  3049.             arg[0] = '\0';
  3050.             sscanf (ccp, fullstr, arg);
  3051.             arglen = strlen (arg);
  3052.             for (cmdp = cmdtable; cmdp->name; cmdp++)    {
  3053.                 if (!strncmpi (cmdp->name, arg, arglen))    {
  3054.                     if (cmdp->states & (1 << cp->type))        {
  3055.                         (*cmdp->fnc)(cp);
  3056.                         if (cp->type != CT_UNKNOWN)
  3057.                             firstcmd = 0;
  3058.                             }
  3059.                     if (firstcmd)
  3060.                         cp->xmitted += usprintf(cp->fd,namecmdstr, stars);
  3061.                             goto loop;
  3062.                     }
  3063.                 }
  3064.             if (firstcmd)
  3065.                 cp->xmitted += usprintf (cp->fd, namecmdstr, stars);
  3066.             else if (cp->type == CT_USER)
  3067.                 cp->xmitted += usprintf (cp->fd, unkcmdstr, unknownstr, arg, gethelpstr);
  3068.             goto loop;
  3069.             }
  3070.         if (firstcmd)    {
  3071.             cp->xmitted += usprintf(cp->fd,namecmdstr, stars);
  3072.             goto loop;
  3073.             }
  3074. #ifndef TNOS_68K
  3075.             if ((ccp = strpbrk (cp->ibuf, "\r\n")) != NULLCHAR)
  3076. #else
  3077.             if ((ccp = strpbrk (cp->ibuf, "\r\l")) != NULLCHAR)
  3078. #endif
  3079.             *ccp = '\0';
  3080. #ifdef NOCTLCHARS
  3081.         if (isprint (cp->ibuf[0]) != 0 && cp->type == CT_USER)
  3082. #else
  3083.         if (cp->type == CT_USER)
  3084. #endif
  3085.             send_msg_to_channel (cp->nickname, cp->channel, cp->ibuf);
  3086.         }
  3087.     sockblock(cp->fd,SOCK_BLOCK);
  3088.     if (m)
  3089.         setflush (cp->fd, -1);
  3090.     bye_command (cp);
  3091.     free_closed_connections ();
  3092. }
  3093.  
  3094.  
  3095. /* Incoming convers session */
  3096. void
  3097. conv_incom(s,t,p)
  3098. int s;
  3099. void *t;
  3100. void *p;
  3101. {
  3102. struct convection *cp;
  3103.  
  3104.     sockowner(s,Curproc);    /* We own it now */
  3105. /*    sockmode(s,SOCK_BINARY);    */
  3106.     sockmode(s,SOCK_ASCII);
  3107.     sockblock(s,SOCK_NOTXBLOCK);   /* prevent backlogs ! */
  3108.     cp = alloc_connection(s);
  3109.     cp->channel = CChannel;
  3110.     statlog ("CONFERENCE - New Telnet User");
  3111.     
  3112.     {
  3113.     struct permlink *pl;
  3114.  
  3115.     for(pl = permlinks; pl; pl = pl->next)
  3116.         if(pl->fd == s) {
  3117.             pl->convection = cp;
  3118.             cp->xmitted += usprintf(s,hhoststr,Chostname);
  3119.             }
  3120.  
  3121.     if(pl == NULLPERMLINK) {
  3122.         cp->xmitted += usprintf(cp->fd,
  3123.             "%s%s %s",conferencestr, Chostname, gethelpstr);
  3124. /*        usprintf(cp->fd,namecmdstr, stars);    */
  3125.         }
  3126.     }
  3127.     process_commands(cp,(struct mbx *) 0);
  3128. }
  3129.  
  3130.  
  3131. #ifdef MAILBOX
  3132. /* this is for Mailbox users */
  3133. void
  3134. mbox_converse(fd, name, channel, mbox)
  3135. int fd;
  3136. char *name;
  3137. int channel;
  3138. struct mbx *mbox;
  3139. {
  3140. struct convection *cp;
  3141.  
  3142.     sockblock(fd,SOCK_NOTXBLOCK);   /* prevent backlogs ! */
  3143.     cp = alloc_connection(fd);
  3144.     cp->channel = (channel == -1) ? CChannel : channel;
  3145.     strcpy(cp->name,name);
  3146.     strcpy (cp->nickname, cp->name);
  3147.     strcpy(cp->host,Chostname);
  3148.     cp->type = CT_USER;
  3149.         cp->flags &= ~CLOSE_SOCK;     /* do not close socket on exit */
  3150.     setflush(fd,'\n');       /* automatic flushing each line */
  3151.     cp->xmitted += usprintf(fd, "%s%s %s", conferencestr, Chostname, gethelpstr);
  3152.     announce_new_user (cp);
  3153.     set_personal(cp);
  3154.     clear_locks();
  3155.     cp->locked = 1; /* send to everyone but ourself */
  3156.     mystatus (cp, (int) -1);
  3157.     process_commands(cp,(mbox) ? mbox : (struct mbx *) 1);
  3158. }
  3159. #endif /* MAILBOX */
  3160.  
  3161. void conversWriteall (str)
  3162. char *str;
  3163. {
  3164. struct convection *p;
  3165. int cnt;
  3166.  
  3167.     for (p = convections; p; p = p->next)
  3168.             if (p->type == CT_USER)
  3169.             usprintf(p->fd,"%s SYSOP: %s\n",amessage, str);
  3170. }
  3171.  
  3172.  
  3173. static void
  3174. convcolorchange (p, str)
  3175. struct convection *p;
  3176. unsigned char *str;
  3177. {
  3178. int old;
  3179.  
  3180.         if (p->flags & USE_COLOR)    {
  3181.             old = Curproc->output;
  3182.             Curproc->output = p->fd;
  3183.             p->xmitted += colorchange (str, p->colorset);
  3184.             Curproc->output = old;
  3185.     }
  3186. }
  3187.  
  3188.  
  3189. static void
  3190. cmdsummary_command(cp)
  3191. struct convection *cp;
  3192. {
  3193. int i;
  3194. char buf[82];
  3195. struct cmdtable *cmdp = cmdtable;
  3196. int width = 11, count = 7;
  3197.  
  3198.     cp->xmitted += usprintf(cp->fd,summary, stars);
  3199.     memset(buf,' ',sizeof(buf));
  3200.     buf[77] = '\n';
  3201.     buf[78] = '\0';
  3202.     for(i=0;cmdp->name;cmdp++,i = ((i+1) % count)){
  3203.         if ((unsigned char)*cmdp->name == 255)
  3204.             break;
  3205.         strncpy(&buf[i * width],cmdp->name,strlen(cmdp->name));
  3206.         if(i == (count - 1)){
  3207.             cp->xmitted = usprintf(cp->fd, "%s ", buf);
  3208.             memset(buf,' ',77);
  3209.         }
  3210.     }
  3211.     if (i)
  3212.         cp->xmitted += usprintf(cp->fd, buf);
  3213.     cp->xmitted += usprintf(cp->fd, trailer);    
  3214. }
  3215.  
  3216. #endif /* CONVERS */
  3217.